haiku/headers/os/translation/TranslatorRoster.h

142 lines
3.7 KiB
C
Raw Normal View History

/*
* Copyright 2002-2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _TRANSLATOR_ROSTER_H
#define _TRANSLATOR_ROSTER_H
#include <Archivable.h>
#include <TranslationDefs.h>
struct translation_format;
class BBitmap;
class BMessage;
class BMessenger;
class BPositionIO;
class BQuery;
class BRect;
class BTranslator;
class BView;
struct entry_ref;
Make sure images containing BTranslators are not unloaded early When a translator is uninstalled, BTranslatorPrivate::_RemoveTranslators is called. This method used to unload the image containing the translator after calling Release() on it resulting in several problems: - If the translator was still busy, e.g. translating something while being installed, it crashed since the image was unloaded even though its refcount was larger than 0. - Applications using code from one of the translators (e.g. its config view) would crash when the translator is uninstalled (this is bug #12005). This problem is now fixed. The roster keeps track of all translators whose image it manages (even if the translator was already removed from the roster). It also keeps a refcount to all images. When a translator's refcount drops to zero and it belonged to a roster at some point, it does not delete itself, but notifies the roster that it is ready to destruct, which then removes it from the roster if the translator is still in it, destroys the translator, decrements the refcount of the image and if the new refcount is zero, unloads the image. All of this is done in a message handler, since if the translator called TranslatorDeleted like before, the unloaded image would be referenced when the stack is walked up. Finally, the DataTranslations preflet is required to Acquire() the translator whose config view it is showing, because otherwise its refcount could be reduced to 0 and the image unloaded. BTranslatorRoster now enables users to acquire a translator by ID. By the time the translator has to be released, it might not be part of the roster anymore though. Since BTranslatorRoster tries not to give out raw pointers to the translators it manages, users who acquire a translator through a roster now are given a BTranslatorReleaseDelegate, which allows for releasing the BTranslator exactly once and then self-destructs. Signed-off-by: Axel Dörfler <axeld@pinc-software.de>
2015-11-08 18:16:05 +03:00
class BTranslatorReleaseDelegate {
public:
BTranslatorReleaseDelegate(BTranslator* translator);
void Release();
private:
BTranslator* fUnderlying;
};
class BTranslatorRoster : public BArchivable {
public:
BTranslatorRoster();
BTranslatorRoster(BMessage* model);
virtual ~BTranslatorRoster();
static BTranslatorRoster* Default();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* from);
status_t AddTranslators(const char* loadPath = NULL);
status_t AddTranslator(BTranslator* translator);
virtual status_t Identify(BPositionIO* source,
BMessage* ioExtension,
translator_info* _info, uint32 hintType = 0,
const char* hintMIME = NULL,
uint32 wantType = 0);
virtual status_t GetTranslators(BPositionIO* source,
BMessage* ioExtension,
translator_info** _info, int32* _numInfo,
uint32 hintType = 0,
const char* hintMIME = NULL,
uint32 wantType = 0);
virtual status_t GetAllTranslators(translator_id** _list,
int32* _count);
virtual status_t GetTranslatorInfo(translator_id translatorID,
const char** _name, const char** _info,
int32* _version);
virtual status_t GetInputFormats(translator_id translatorID,
const translation_format** _formats,
int32* _numFormats);
virtual status_t GetOutputFormats(translator_id translatorID,
const translation_format** _formats,
int32* _numFormats);
virtual status_t Translate(BPositionIO* source,
const translator_info* info,
BMessage* ioExtension,
BPositionIO* destination,
uint32 wantOutType, uint32 hintType = 0,
const char* hintMIME = NULL);
virtual status_t Translate(translator_id translatorID,
BPositionIO* source, BMessage* ioExtension,
BPositionIO* destination,
uint32 wantOutType);
virtual status_t MakeConfigurationView(
translator_id translatorID,
BMessage* ioExtension, BView** _view,
BRect* _extent);
virtual status_t GetConfigurationMessage(
translator_id translatorID,
BMessage* ioExtension);
Make sure images containing BTranslators are not unloaded early When a translator is uninstalled, BTranslatorPrivate::_RemoveTranslators is called. This method used to unload the image containing the translator after calling Release() on it resulting in several problems: - If the translator was still busy, e.g. translating something while being installed, it crashed since the image was unloaded even though its refcount was larger than 0. - Applications using code from one of the translators (e.g. its config view) would crash when the translator is uninstalled (this is bug #12005). This problem is now fixed. The roster keeps track of all translators whose image it manages (even if the translator was already removed from the roster). It also keeps a refcount to all images. When a translator's refcount drops to zero and it belonged to a roster at some point, it does not delete itself, but notifies the roster that it is ready to destruct, which then removes it from the roster if the translator is still in it, destroys the translator, decrements the refcount of the image and if the new refcount is zero, unloads the image. All of this is done in a message handler, since if the translator called TranslatorDeleted like before, the unloaded image would be referenced when the stack is walked up. Finally, the DataTranslations preflet is required to Acquire() the translator whose config view it is showing, because otherwise its refcount could be reduced to 0 and the image unloaded. BTranslatorRoster now enables users to acquire a translator by ID. By the time the translator has to be released, it might not be part of the roster anymore though. Since BTranslatorRoster tries not to give out raw pointers to the translators it manages, users who acquire a translator through a roster now are given a BTranslatorReleaseDelegate, which allows for releasing the BTranslator exactly once and then self-destructs. Signed-off-by: Axel Dörfler <axeld@pinc-software.de>
2015-11-08 18:16:05 +03:00
BTranslatorReleaseDelegate* AcquireTranslator(int32 translatorID);
status_t GetRefFor(translator_id translatorID,
entry_ref* ref);
bool IsTranslator(entry_ref* ref);
status_t StartWatching(BMessenger target);
status_t StopWatching(BMessenger target);
class Private;
private:
// unimplemented
BTranslatorRoster(
const BTranslatorRoster& other);
BTranslatorRoster& operator=(const BTranslatorRoster& other);
virtual void ReservedTranslatorRoster1();
virtual void ReservedTranslatorRoster2();
virtual void ReservedTranslatorRoster3();
virtual void ReservedTranslatorRoster4();
virtual void ReservedTranslatorRoster5();
virtual void ReservedTranslatorRoster6();
void _Initialize();
static const char* Version(int32* outCurVersion,
int32* outMinVersion,
int32 inAppVersion);
// for backward compatiblity only
private:
friend class Private;
Private* fPrivate;
int32 fUnused[6];
static BTranslatorRoster* sDefaultRoster;
};
#endif // _TRANSLATOR_ROSTER_H