Turned the loaded images map into a singleton.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34368 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-11-30 11:40:20 +00:00
parent adcb834590
commit 4a6fb0a865
+109 -56
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2009, Haiku. * Copyright 2001-2009, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -12,6 +12,10 @@
/*! BShelf stores replicant views that are dropped onto it */ /*! BShelf stores replicant views that are dropped onto it */
#include <Shelf.h>
#include <pthread.h>
#include <AutoLock.h> #include <AutoLock.h>
#include <Beep.h> #include <Beep.h>
#include <Dragger.h> #include <Dragger.h>
@@ -24,7 +28,6 @@
#include <Point.h> #include <Point.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <Rect.h> #include <Rect.h>
#include <Shelf.h>
#include <String.h> #include <String.h>
#include <View.h> #include <View.h>
@@ -39,32 +42,78 @@
#include <utility> #include <utility>
namespace {
typedef std::map<BString, std::pair<image_id, int32> > LoadedImageMap; typedef std::map<BString, std::pair<image_id, int32> > LoadedImageMap;
static LoadedImageMap sLoadedImages;
static BLocker sLoadedImageMapLocker("BShelf loaded image map"); struct LoadedImages {
LoadedImageMap images;
LoadedImages()
:
fLock("BShelf loaded image map")
{
}
bool Lock()
{
return fLock.Lock();
}
void Unlock()
{
fLock.Unlock();
}
static LoadedImages* Default()
{
if (sDefaultInstance == NULL)
pthread_once(&sDefaultInitOnce, &_InitSingleton);
return sDefaultInstance;
}
private:
static void _InitSingleton()
{
sDefaultInstance = new LoadedImages;
}
private:
BLocker fLock;
static pthread_once_t sDefaultInitOnce;
static LoadedImages* sDefaultInstance;
};
pthread_once_t LoadedImages::sDefaultInitOnce = PTHREAD_ONCE_INIT;
LoadedImages* LoadedImages::sDefaultInstance = NULL;
} // unnamed namespace
static property_info sShelfPropertyList[] = { static property_info sShelfPropertyList[] = {
{ {
"Replicant", "Replicant",
{ B_COUNT_PROPERTIES, B_CREATE_PROPERTY }, { B_COUNT_PROPERTIES, B_CREATE_PROPERTY },
{ B_DIRECT_SPECIFIER }, { B_DIRECT_SPECIFIER },
NULL, 0, NULL, 0,
}, },
{ {
"Replicant", "Replicant",
{ B_DELETE_PROPERTY, B_GET_PROPERTY }, { B_DELETE_PROPERTY, B_GET_PROPERTY },
{ B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, B_ID_SPECIFIER }, { B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, B_ID_SPECIFIER },
NULL, 0, NULL, 0,
}, },
{ {
"Replicant", "Replicant",
{}, {},
{ B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, B_ID_SPECIFIER }, { B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, B_ID_SPECIFIER },
"... of Replicant {index | name | id} of ...", 0, "... of Replicant {index | name | id} of ...", 0,
}, },
{ 0, { 0 }, { 0 }, 0, 0 } { 0, { 0 }, { 0 }, 0, 0 }
}; };
@@ -75,7 +124,7 @@ static property_info sReplicantPropertyList[] = {
{ B_DIRECT_SPECIFIER }, { B_DIRECT_SPECIFIER },
NULL, 0, { B_INT32_TYPE } NULL, 0, { B_INT32_TYPE }
}, },
{ {
"Name", "Name",
{ B_GET_PROPERTY }, { B_GET_PROPERTY },
@@ -103,7 +152,7 @@ static property_info sReplicantPropertyList[] = {
{ B_DIRECT_SPECIFIER }, { B_DIRECT_SPECIFIER },
NULL, 0, NULL, 0,
}, },
{ 0, { 0 }, { 0 }, 0, 0 } { 0, { 0 }, { 0 }, 0, 0 }
}; };
@@ -123,7 +172,7 @@ struct replicant_data {
static int32 IndexOf(BList const *list, BMessage const *msg); static int32 IndexOf(BList const *list, BMessage const *msg);
static int32 IndexOf(BList const *list, BView const *view, bool allowZombie); static int32 IndexOf(BList const *list, BView const *view, bool allowZombie);
static int32 IndexOf(BList const *list, unsigned long id); static int32 IndexOf(BList const *list, unsigned long id);
status_t Archive(BMessage *msg); status_t Archive(BMessage *msg);
BMessage* message; BMessage* message;
@@ -247,7 +296,7 @@ replicant_data::Archive(BMessage* msg)
if (view && (view->Archive(&archive) == B_OK)) { if (view && (view->Archive(&archive) == B_OK)) {
msg->AddInt32("uniqueid", id); msg->AddInt32("uniqueid", id);
BPoint pos (0,0); BPoint pos (0,0);
if (view) { if (view) {
msg->AddMessage("message", &archive); msg->AddMessage("message", &archive);
pos = view->Frame().LeftTop(); pos = view->Frame().LeftTop();
} else if (zombie_view) } else if (zombie_view)
@@ -364,7 +413,7 @@ replicant_data::IndexOf(BList const *list, unsigned long id)
ShelfContainerViewFilter::ShelfContainerViewFilter(BShelf *shelf, BView *view) ShelfContainerViewFilter::ShelfContainerViewFilter(BShelf *shelf, BView *view)
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fShelf(shelf), fShelf(shelf),
fView(view) fView(view)
{ {
} }
@@ -420,7 +469,7 @@ ShelfContainerViewFilter::_ObjectDropFilter(BMessage *msg, BHandler **_handler)
rect = dragger->fTarget->Frame(); rect = dragger->fTarget->Frame();
rect.OffsetTo(point); rect.OffsetTo(point);
point = rect.LeftTop() + fShelf->AdjustReplicantBy(rect, msg); point = rect.LeftTop() + fShelf->AdjustReplicantBy(rect, msg);
if (dragger->fRelation == BDragger::TARGET_IS_PARENT) if (dragger->fRelation == BDragger::TARGET_IS_PARENT)
dragger->fTarget->MoveTo(point); dragger->fTarget->MoveTo(point);
else if (dragger->fRelation == BDragger::TARGET_IS_CHILD) else if (dragger->fRelation == BDragger::TARGET_IS_CHILD)
@@ -428,7 +477,7 @@ ShelfContainerViewFilter::_ObjectDropFilter(BMessage *msg, BHandler **_handler)
else { else {
//TODO: TARGET_UNKNOWN/TARGET_SIBLING //TODO: TARGET_UNKNOWN/TARGET_SIBLING
} }
} else { } else {
if (fShelf->_AddReplicant(msg, &point, fShelf->fGenCount++) == B_OK) if (fShelf->_AddReplicant(msg, &point, fShelf->fGenCount++) == B_OK)
Looper()->DetachCurrentMessage(); Looper()->DetachCurrentMessage();
@@ -445,7 +494,7 @@ ReplicantViewFilter::ReplicantViewFilter(BShelf *shelf, BView *view)
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fShelf(shelf), fShelf(shelf),
fView(view) fView(view)
{ {
} }
@@ -616,12 +665,12 @@ BShelf::MessageReceived(BMessage *msg)
break; break;
} }
return BHandler::MessageReceived(msg); return BHandler::MessageReceived(msg);
case B_CREATE_PROPERTY: case B_CREATE_PROPERTY:
{ {
BMessage replicantMsg; BMessage replicantMsg;
BPoint pos; BPoint pos;
if (msg->FindMessage("data", &replicantMsg) == B_OK if (msg->FindMessage("data", &replicantMsg) == B_OK
&& msg->FindPoint("location", &pos) == B_OK) { && msg->FindPoint("location", &pos) == B_OK) {
err = AddReplicant(&replicantMsg, pos); err = AddReplicant(&replicantMsg, pos);
} }
@@ -635,7 +684,7 @@ BShelf::MessageReceived(BMessage *msg)
if (err == B_BAD_SCRIPT_SYNTAX) if (err == B_BAD_SCRIPT_SYNTAX)
replyMsg.AddString("message", "Didn't understand the specifier(s)"); replyMsg.AddString("message", "Didn't understand the specifier(s)");
else else
replyMsg.AddString("message", strerror(err)); replyMsg.AddString("message", strerror(err));
} }
replyMsg.AddInt32("error", err); replyMsg.AddInt32("error", err);
@@ -689,7 +738,7 @@ BShelf::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier,
BPropertyInfo shelfPropInfo(sShelfPropertyList); BPropertyInfo shelfPropInfo(sShelfPropertyList);
BHandler *target = NULL; BHandler *target = NULL;
BView *replicant = NULL; BView *replicant = NULL;
switch (shelfPropInfo.FindMatch(msg, 0, specifier, form, property)) { switch (shelfPropInfo.FindMatch(msg, 0, specifier, form, property)) {
case 0: case 0:
target = this; target = this;
@@ -1072,7 +1121,7 @@ BShelf::_Archive(BMessage *data) const
data->AddMessage("replicant", &archive); data->AddMessage("replicant", &archive);
archive.MakeEmpty(); archive.MakeEmpty();
} }
return B_OK; return B_OK;
} }
@@ -1128,7 +1177,7 @@ BShelf::_InitData(BEntry *entry, BDataIO *stream, BView *view,
replmsg = new BMessage(); replmsg = new BMessage();
replicant.FindPoint("position", &point); replicant.FindPoint("position", &point);
replicant.FindMessage("message", replmsg); replicant.FindMessage("message", replmsg);
AddReplicant(replmsg, point); AddReplicant(replmsg, point);
} }
} }
} }
@@ -1151,15 +1200,15 @@ BShelf::_DeleteReplicant(replicant_data* item)
int32 index = replicant_data::IndexOf(&fReplicants, item->message); int32 index = replicant_data::IndexOf(&fReplicants, item->message);
ReplicantDeleted(index, item->message, view); ReplicantDeleted(index, item->message, view);
fReplicants.RemoveItem(item); fReplicants.RemoveItem(item);
if (item->relation == BDragger::TARGET_IS_PARENT if (item->relation == BDragger::TARGET_IS_PARENT
|| item->relation == BDragger::TARGET_IS_SIBLING) { || item->relation == BDragger::TARGET_IS_SIBLING) {
delete view; delete view;
} }
if (item->relation == BDragger::TARGET_IS_CHILD if (item->relation == BDragger::TARGET_IS_CHILD
|| item->relation == BDragger::TARGET_IS_SIBLING) { || item->relation == BDragger::TARGET_IS_SIBLING) {
delete item->dragger; delete item->dragger;
} }
@@ -1167,15 +1216,17 @@ BShelf::_DeleteReplicant(replicant_data* item)
const char* signature = NULL; const char* signature = NULL;
if (item->message->FindString("add_on", &signature) == B_OK if (item->message->FindString("add_on", &signature) == B_OK
&& signature != NULL) { && signature != NULL) {
AutoLock<BLocker> lock(sLoadedImageMapLocker); LoadedImages* loadedImages = LoadedImages::Default();
AutoLock<LoadedImages> lock(loadedImages);
if (lock.IsLocked()) { if (lock.IsLocked()) {
LoadedImageMap::iterator it = sLoadedImages.find(BString(signature)); LoadedImageMap::iterator it = loadedImages->images.find(
BString(signature));
if (it != sLoadedImages.end()) { if (it != loadedImages->images.end()) {
(*it).second.second--; (*it).second.second--;
if ((*it).second.second <= 0) { if ((*it).second.second <= 0) {
unload_add_on((*it).second.first); unload_add_on((*it).second.first);
sLoadedImages.erase(it); loadedImages->images.erase(it);
} }
} }
} }
@@ -1221,8 +1272,8 @@ BShelf::_AddReplicant(BMessage *data, BPoint *location, uint32 uniqueID)
const char *addOn = NULL; const char *addOn = NULL;
if (data->FindString("class", &className) == B_OK if (data->FindString("class", &className) == B_OK
&& data->FindString("add_on", &addOn) == B_OK) { && data->FindString("add_on", &addOn) == B_OK) {
if (find_replicant(fReplicants, className, addOn)) { if (find_replicant(fReplicants, className, addOn)) {
printf("Replicant was rejected. Unique replicant already exists. class=%s, signature=%s", printf("Replicant was rejected. Unique replicant already exists. class=%s, signature=%s",
className, addOn); className, addOn);
return send_reply(data, B_ERROR, uniqueID); return send_reply(data, B_ERROR, uniqueID);
@@ -1264,12 +1315,14 @@ BShelf::_AddReplicant(BMessage *data, BPoint *location, uint32 uniqueID)
// Update use count for image // Update use count for image
const char* signature = NULL; const char* signature = NULL;
if (data->FindString("add_on", &signature) == B_OK && signature != NULL) { if (data->FindString("add_on", &signature) == B_OK && signature != NULL) {
AutoLock<BLocker> lock(sLoadedImageMapLocker); LoadedImages* loadedImages = LoadedImages::Default();
AutoLock<LoadedImages> lock(loadedImages);
if (lock.IsLocked()) { if (lock.IsLocked()) {
LoadedImageMap::iterator it = sLoadedImages.find(BString(signature)); LoadedImageMap::iterator it = loadedImages->images.find(
BString(signature));
if (it == sLoadedImages.end()) if (it == loadedImages->images.end())
sLoadedImages.insert(LoadedImageMap::value_type( loadedImages->images.insert(LoadedImageMap::value_type(
BString(signature), std::pair<image_id, int>(image, 1))); BString(signature), std::pair<image_id, int>(image, 1)));
else else
(*it).second.second++; (*it).second.second++;
@@ -1298,7 +1351,7 @@ BShelf::_GetReplicant(BMessage *data, BView *view, const BPoint &point,
// TODO: test me -- there seems to be lots of bugs parked here! // TODO: test me -- there seems to be lots of bugs parked here!
BView *replicant = NULL; BView *replicant = NULL;
_GetReplicantData(data, view, replicant, dragger, relation); _GetReplicantData(data, view, replicant, dragger, relation);
if (dragger != NULL) if (dragger != NULL)
dragger->_SetViewToDrag(replicant); dragger->_SetViewToDrag(replicant);
@@ -1306,32 +1359,32 @@ BShelf::_GetReplicant(BMessage *data, BView *view, const BPoint &point,
if (!CanAcceptReplicantView(frame, replicant, data)) { if (!CanAcceptReplicantView(frame, replicant, data)) {
// the view has not been accepted // the view has not been accepted
if (relation == BDragger::TARGET_IS_PARENT if (relation == BDragger::TARGET_IS_PARENT
|| relation == BDragger::TARGET_IS_SIBLING) { || relation == BDragger::TARGET_IS_SIBLING) {
delete replicant; delete replicant;
} }
if (relation == BDragger::TARGET_IS_CHILD if (relation == BDragger::TARGET_IS_CHILD
|| relation == BDragger::TARGET_IS_SIBLING) { || relation == BDragger::TARGET_IS_SIBLING) {
delete dragger; delete dragger;
} }
return NULL; return NULL;
} }
BPoint adjust = AdjustReplicantBy(frame, data); BPoint adjust = AdjustReplicantBy(frame, data);
if (dragger != NULL) if (dragger != NULL)
dragger->_SetShelf(this); dragger->_SetShelf(this);
// TODO: could be not correct for some relations // TODO: could be not correct for some relations
view->MoveTo(point + adjust); view->MoveTo(point + adjust);
// if it's a sibling or a child, we need to add the dragger // if it's a sibling or a child, we need to add the dragger
if (relation == BDragger::TARGET_IS_SIBLING if (relation == BDragger::TARGET_IS_SIBLING
|| relation == BDragger::TARGET_IS_CHILD) || relation == BDragger::TARGET_IS_CHILD)
fContainerView->AddChild(dragger); fContainerView->AddChild(dragger);
if (relation != BDragger::TARGET_IS_CHILD) if (relation != BDragger::TARGET_IS_CHILD)
fContainerView->AddChild(replicant); fContainerView->AddChild(replicant);
replicant->AddFilter(new ReplicantViewFilter(this, replicant)); replicant->AddFilter(new ReplicantViewFilter(this, replicant));
return replicant; return replicant;
@@ -1349,18 +1402,18 @@ BShelf::_GetReplicantData(BMessage *data, BView *view, BView *&replicant,
image_id draggerImage = B_ERROR; image_id draggerImage = B_ERROR;
replicant = view; replicant = view;
dragger = dynamic_cast<BDragger*>(_InstantiateObject(&widget, &draggerImage)); dragger = dynamic_cast<BDragger*>(_InstantiateObject(&widget, &draggerImage));
// Replicant is a sibling, or unknown, if there isn't a dragger // Replicant is a sibling, or unknown, if there isn't a dragger
if (dragger != NULL) if (dragger != NULL)
relation = BDragger::TARGET_IS_SIBLING; relation = BDragger::TARGET_IS_SIBLING;
} else if ((dragger = dynamic_cast<BDragger*>(view)) != NULL) { } else if ((dragger = dynamic_cast<BDragger*>(view)) != NULL) {
// Replicant is child of the dragger // Replicant is child of the dragger
relation = BDragger::TARGET_IS_CHILD; relation = BDragger::TARGET_IS_CHILD;
replicant = dragger->ChildAt(0); replicant = dragger->ChildAt(0);
} else { } else {
// Replicant is parent of the dragger // Replicant is parent of the dragger
relation = BDragger::TARGET_IS_PARENT; relation = BDragger::TARGET_IS_PARENT;
replicant = view; replicant = view;
dragger = dynamic_cast<BDragger *>(replicant->FindView("_dragger_")); dragger = dynamic_cast<BDragger *>(replicant->FindView("_dragger_"));
// can be NULL, the replicant could not have a dragger at all // can be NULL, the replicant could not have a dragger at all
@@ -1411,7 +1464,7 @@ BShelf::_GetProperty(BMessage *msg, BMessage *reply)
switch (msg->what) { switch (msg->what) {
case B_INDEX_SPECIFIER: { case B_INDEX_SPECIFIER: {
int32 index = -1; int32 index = -1;
if (msg->FindInt32("index", &index)!=B_OK) if (msg->FindInt32("index", &index)!=B_OK)
break; break;
ReplicantAt(index, &replicant, &ID, &err); ReplicantAt(index, &replicant, &ID, &err);
break; break;
@@ -1431,7 +1484,7 @@ BShelf::_GetProperty(BMessage *msg, BMessage *reply)
BView *view = NULL; BView *view = NULL;
ReplicantAt(i, &view, &ID, &err); ReplicantAt(i, &view, &ID, &err);
if (err == B_OK) { if (err == B_OK) {
if (view->Name() != NULL && if (view->Name() != NULL &&
strlen(view->Name()) == strlen(name) && !strcmp(view->Name(), name)) { strlen(view->Name()) == strlen(name) && !strcmp(view->Name(), name)) {
replicant = view; replicant = view;
break; break;