Added EventQueue and Event and MessageRunnerManager classes used for the
registrar side message runner support. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1498 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
3a93f97d52
commit
44c3726b9d
83
src/servers/registrar/Event.cpp
Normal file
83
src/servers/registrar/Event.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Event.cpp
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// YellowBites (http://www.yellowbites.com)
|
||||
// Description: Base class for events as handled by EventQueue.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
// constructor
|
||||
Event::Event(bool autoDelete)
|
||||
: fTime(0),
|
||||
fAutoDelete(autoDelete)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Event::Event(bigtime_t time, bool autoDelete)
|
||||
: fTime(time),
|
||||
fAutoDelete(autoDelete)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
Event::~Event()
|
||||
{
|
||||
}
|
||||
|
||||
// SetTime
|
||||
void
|
||||
Event::SetTime(bigtime_t time)
|
||||
{
|
||||
fTime = time;
|
||||
}
|
||||
|
||||
// Time
|
||||
bigtime_t
|
||||
Event::Time() const
|
||||
{
|
||||
return fTime;
|
||||
}
|
||||
|
||||
// SetAutoDelete
|
||||
void
|
||||
Event::SetAutoDelete(bool autoDelete)
|
||||
{
|
||||
fAutoDelete = autoDelete;
|
||||
}
|
||||
|
||||
// IsAutoDelete
|
||||
bool
|
||||
Event::IsAutoDelete() const
|
||||
{
|
||||
return fAutoDelete;
|
||||
}
|
||||
|
||||
// Do
|
||||
bool
|
||||
Event::Do()
|
||||
{
|
||||
return fAutoDelete;
|
||||
}
|
||||
|
52
src/servers/registrar/Event.h
Normal file
52
src/servers/registrar/Event.h
Normal file
@ -0,0 +1,52 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Event.h
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// YellowBites (http://www.yellowbites.com)
|
||||
// Description: Base class for events as handled by EventQueue.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
class Event {
|
||||
public:
|
||||
Event(bool autoDelete = true);
|
||||
Event(bigtime_t time, bool autoDelete = true);
|
||||
virtual ~Event();
|
||||
|
||||
void SetTime(bigtime_t time);
|
||||
bigtime_t Time() const;
|
||||
|
||||
void SetAutoDelete(bool autoDelete);
|
||||
bool IsAutoDelete() const;
|
||||
|
||||
virtual bool Do();
|
||||
|
||||
private:
|
||||
bigtime_t fTime;
|
||||
bool fAutoDelete;
|
||||
};
|
||||
|
||||
#endif // EVENT_H
|
216
src/servers/registrar/EventQueue.cpp
Normal file
216
src/servers/registrar/EventQueue.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: EventQueue.cpp
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// YellowBites (http://www.yellowbites.com)
|
||||
// Description: A class featuring providing a mechanism to do events at
|
||||
// specified times.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#include "EventQueue.h"
|
||||
|
||||
static const char *kDefaultEventQueueName = "event looper";
|
||||
|
||||
// constructor
|
||||
EventQueue::EventQueue(const char *name)
|
||||
: fEvents(100),
|
||||
fEventLooper(-1),
|
||||
fLooperControl(-1),
|
||||
fNextEventTime(0),
|
||||
fStatus(B_ERROR)
|
||||
|
||||
{
|
||||
if (!name)
|
||||
name = kDefaultEventQueueName;
|
||||
fLooperControl = create_sem(0, (BString(name) += " control").String());
|
||||
if (fLooperControl >= B_OK)
|
||||
fStatus = B_OK;
|
||||
else
|
||||
fStatus = fLooperControl;
|
||||
if (fStatus == B_OK) {
|
||||
fEventLooper = spawn_thread(_EventLooperEntry, name, B_NORMAL_PRIORITY,
|
||||
this);
|
||||
if (fEventLooper >= B_OK) {
|
||||
fStatus = B_OK;
|
||||
resume_thread(fEventLooper);
|
||||
} else
|
||||
fStatus = fEventLooper;
|
||||
}
|
||||
}
|
||||
|
||||
// destructor
|
||||
EventQueue::~EventQueue()
|
||||
{
|
||||
Die();
|
||||
while (Event *event = (Event*)fEvents.RemoveItem(0L)) {
|
||||
if (event->IsAutoDelete())
|
||||
delete event;
|
||||
}
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
EventQueue::InitCheck()
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
// Die
|
||||
void
|
||||
EventQueue::Die()
|
||||
{
|
||||
if (delete_sem(fLooperControl) == B_OK) {
|
||||
int32 dummy;
|
||||
wait_for_thread(fEventLooper, &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
// AddEvent
|
||||
bool
|
||||
EventQueue::AddEvent(Event *event)
|
||||
{
|
||||
Lock();
|
||||
bool result = _AddEvent(event);
|
||||
if (result)
|
||||
_Reschedule();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
// RemoveEvent
|
||||
bool
|
||||
EventQueue::RemoveEvent(Event *event)
|
||||
{
|
||||
bool result = false;
|
||||
Lock();
|
||||
if ((result = fEvents.RemoveItem(event)))
|
||||
_Reschedule();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
// ModifyEvent
|
||||
void
|
||||
EventQueue::ModifyEvent(Event *event, bigtime_t newTime)
|
||||
{
|
||||
Lock();
|
||||
if (fEvents.RemoveItem(event)) {
|
||||
event->SetTime(newTime);
|
||||
_AddEvent(event);
|
||||
_Reschedule();
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// _AddEvent
|
||||
//
|
||||
// PRE: The object must be locked.
|
||||
bool
|
||||
EventQueue::_AddEvent(Event *event)
|
||||
{
|
||||
// find the insertion index
|
||||
int32 lower = 0;
|
||||
int32 upper = fEvents.CountItems();
|
||||
while (lower < upper) {
|
||||
int32 mid = (lower + upper) / 2;
|
||||
Event* midEvent = _EventAt(mid);
|
||||
if (event->Time() < midEvent->Time())
|
||||
upper = mid;
|
||||
else
|
||||
lower = mid + 1;
|
||||
}
|
||||
return fEvents.AddItem(event, lower);
|
||||
}
|
||||
|
||||
// _EventAt
|
||||
Event*
|
||||
EventQueue::_EventAt(int32 index) const
|
||||
{
|
||||
return (Event*)fEvents.ItemAt(index);
|
||||
}
|
||||
|
||||
// _EventLooperEntry
|
||||
int32
|
||||
EventQueue::_EventLooperEntry(void *data)
|
||||
{
|
||||
return ((EventQueue*)data)->_EventLooper();
|
||||
}
|
||||
|
||||
// _EventLooper
|
||||
int32
|
||||
EventQueue::_EventLooper()
|
||||
{
|
||||
bool running = true;
|
||||
while (running) {
|
||||
bigtime_t waitUntil = B_INFINITE_TIMEOUT;
|
||||
if (Lock()) {
|
||||
if (!fEvents.IsEmpty())
|
||||
waitUntil = _EventAt(0)->Time();
|
||||
fNextEventTime = waitUntil;
|
||||
Unlock();
|
||||
}
|
||||
status_t err = acquire_sem_etc(fLooperControl, 1, B_ABSOLUTE_TIMEOUT,
|
||||
waitUntil);
|
||||
switch (err) {
|
||||
case B_TIMED_OUT:
|
||||
// do events, that are supposed to go off
|
||||
while (Lock() && !fEvents.IsEmpty()
|
||||
&& system_time() >= _EventAt(0)->Time()) {
|
||||
Event *event = (Event*)fEvents.RemoveItem(0L);
|
||||
Unlock();
|
||||
bool autoDeleteEvent = event->IsAutoDelete();
|
||||
bool deleteEvent = event->Do() || autoDeleteEvent;
|
||||
if (deleteEvent)
|
||||
delete event;
|
||||
}
|
||||
if (IsLocked())
|
||||
Unlock();
|
||||
break;
|
||||
case B_BAD_SEM_ID:
|
||||
running = false;
|
||||
break;
|
||||
case B_OK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// _Reschedule
|
||||
//
|
||||
// PRE: The object must be locked.
|
||||
void
|
||||
EventQueue::_Reschedule()
|
||||
{
|
||||
if (fStatus == B_OK) {
|
||||
if (!fEvents.IsEmpty() && _EventAt(0)->Time() < fNextEventTime)
|
||||
release_sem(fLooperControl);
|
||||
}
|
||||
}
|
||||
|
66
src/servers/registrar/EventQueue.h
Normal file
66
src/servers/registrar/EventQueue.h
Normal file
@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: EventQueue.h
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// YellowBites (http://www.yellowbites.com)
|
||||
// Description: A class featuring providing a mechanism to do events at
|
||||
// specified times.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef EVENT_QUEUE_H
|
||||
#define EVENT_QUEUE_H
|
||||
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
#include <OS.h>
|
||||
|
||||
class Event;
|
||||
|
||||
class EventQueue : public BLocker {
|
||||
public:
|
||||
EventQueue(const char *name = NULL);
|
||||
virtual ~EventQueue();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
void Die();
|
||||
|
||||
bool AddEvent(Event *event);
|
||||
bool RemoveEvent(Event *event);
|
||||
void ModifyEvent(Event *event, bigtime_t newTime);
|
||||
|
||||
private:
|
||||
bool _AddEvent(Event *event);
|
||||
Event *_EventAt(int32 index) const;
|
||||
|
||||
static int32 _EventLooperEntry(void *data);
|
||||
int32 _EventLooper();
|
||||
void _Reschedule();
|
||||
|
||||
BList fEvents;
|
||||
thread_id fEventLooper;
|
||||
sem_id fLooperControl;
|
||||
volatile bigtime_t fNextEventTime;
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
#endif // EVENT_QUEUE_H
|
@ -7,6 +7,9 @@ UsePrivateHeaders storage ;
|
||||
Server obos_registrar :
|
||||
AppInfoList.cpp
|
||||
ClipboardHandler.cpp
|
||||
Event.cpp
|
||||
EventQueue.cpp
|
||||
MessageRunnerManager.cpp
|
||||
MIMEManager.cpp
|
||||
Registrar.cpp
|
||||
RosterAppInfo.cpp
|
||||
|
519
src/servers/registrar/MessageRunnerManager.cpp
Normal file
519
src/servers/registrar/MessageRunnerManager.cpp
Normal file
@ -0,0 +1,519 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: MessageRunnerManager.cpp
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// Description: Manages the registrar side "shadows" of BMessageRunners.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <algobase.h>
|
||||
#include <new.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <OS.h>
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
#include "Debug.h"
|
||||
#include "Event.h"
|
||||
#include "EventQueue.h"
|
||||
#include "MessageRunnerManager.h"
|
||||
|
||||
// the minimal time interval for message runners
|
||||
static const bigtime_t kMininalTimeInterval = 50000LL;
|
||||
|
||||
// RunnerEvent
|
||||
class MessageRunnerManager::RunnerEvent : public Event {
|
||||
public:
|
||||
RunnerEvent(MessageRunnerManager *manager, RunnerInfo *info)
|
||||
: Event(false),
|
||||
fManager(manager),
|
||||
fInfo(info)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Do()
|
||||
{
|
||||
return fManager->_DoEvent(fInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
MessageRunnerManager *fManager;
|
||||
RunnerInfo *fInfo;
|
||||
};
|
||||
|
||||
|
||||
// RunnerInfo
|
||||
struct MessageRunnerManager::RunnerInfo {
|
||||
RunnerInfo(team_id team, int32 token, BMessenger target, BMessage *message,
|
||||
bigtime_t interval, int32 count, BMessenger replyTarget)
|
||||
: team(team),
|
||||
token(token),
|
||||
target(target),
|
||||
message(message),
|
||||
interval(interval),
|
||||
count(count),
|
||||
replyTarget(replyTarget),
|
||||
time(0),
|
||||
event(NULL),
|
||||
rescheduled(false)
|
||||
{
|
||||
}
|
||||
|
||||
~RunnerInfo()
|
||||
{
|
||||
delete message;
|
||||
delete event;
|
||||
}
|
||||
|
||||
status_t DeliverMessage()
|
||||
{
|
||||
if (count > 0)
|
||||
count--;
|
||||
status_t error = target.SendMessage(message, replyTarget, 0);
|
||||
// B_WOULD_BLOCK is as good as B_OK. We return an error only, if
|
||||
// there are serious problems with the target, i.e. if it doesn't
|
||||
// exist anymore for instance. A full message port is harmless.
|
||||
if (error == B_WOULD_BLOCK)
|
||||
error = B_OK;
|
||||
return error;
|
||||
}
|
||||
|
||||
team_id team;
|
||||
int32 token;
|
||||
BMessenger target;
|
||||
BMessage *message;
|
||||
bigtime_t interval;
|
||||
int32 count;
|
||||
BMessenger replyTarget;
|
||||
bigtime_t time;
|
||||
RunnerEvent *event;
|
||||
bool rescheduled;
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
MessageRunnerManager::MessageRunnerManager(EventQueue *eventQueue)
|
||||
: fRunnerInfos(),
|
||||
fLock(),
|
||||
fEventQueue(eventQueue),
|
||||
fNextToken(0)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
MessageRunnerManager::~MessageRunnerManager()
|
||||
{
|
||||
// The event queue should already be stopped, but must still exist.
|
||||
// If it is still running and an event gets executed after we've locked
|
||||
// ourselves, then it will access an already deleted manager.
|
||||
BAutolock _lock(fLock);
|
||||
for (int32 i = 0; RunnerInfo *info = _InfoAt(i); i++) {
|
||||
if (!fEventQueue->RemoveEvent(info->event))
|
||||
info->event = NULL;
|
||||
delete info;
|
||||
}
|
||||
fRunnerInfos.MakeEmpty();
|
||||
}
|
||||
|
||||
// HandleRegisterRunner
|
||||
void
|
||||
MessageRunnerManager::HandleRegisterRunner(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
status_t error = B_OK;
|
||||
// get the parameters
|
||||
team_id team;
|
||||
BMessenger target;
|
||||
// TODO: This should be a "new (nothrow)", but R5's BMessage doesn't
|
||||
// define that version.
|
||||
BMessage *message = new BMessage;
|
||||
bigtime_t interval;
|
||||
int32 count;
|
||||
BMessenger replyTarget;
|
||||
if (error == B_OK && message == NULL)
|
||||
error = B_NO_MEMORY;
|
||||
if (error == B_OK && request->FindInt32("team", &team) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK && request->FindMessenger("target", &target) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK && request->FindMessage("message", message) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK && request->FindInt64("interval", &interval) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK && request->FindInt32("count", &count) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK
|
||||
&& request->FindMessenger("reply_target", &replyTarget) != B_OK) {
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
// check the parameters
|
||||
if (error == B_OK && count == 0)
|
||||
error = B_BAD_VALUE;
|
||||
// add a new runner info
|
||||
RunnerInfo *info = NULL;
|
||||
if (error == B_OK) {
|
||||
interval = max(interval, kMininalTimeInterval);
|
||||
info = new(nothrow) RunnerInfo(team, _NextToken(), target, message,
|
||||
interval, count, replyTarget);
|
||||
if (info) {
|
||||
info->time = system_time();
|
||||
if (!_AddInfo(info))
|
||||
error = B_NO_MEMORY;
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// create a new event
|
||||
RunnerEvent *event = NULL;
|
||||
if (error == B_OK) {
|
||||
event = new(nothrow) RunnerEvent(this, info);
|
||||
if (event) {
|
||||
info->event = event;
|
||||
if (!_ScheduleEvent(info))
|
||||
error = B_NO_MEMORY; // TODO: The only possible reason?
|
||||
} else
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
// cleanup on error
|
||||
if (error != B_OK) {
|
||||
if (info) {
|
||||
_RemoveInfo(info);
|
||||
delete info;
|
||||
}
|
||||
delete message;
|
||||
}
|
||||
// reply to the request
|
||||
if (error == B_OK) {
|
||||
BMessage reply(B_REG_SUCCESS);
|
||||
reply.AddInt32("token", info->token);
|
||||
request->SendReply(&reply);
|
||||
} else {
|
||||
BMessage reply(B_REG_ERROR);
|
||||
reply.AddInt32("error", error);
|
||||
request->SendReply(&reply);
|
||||
}
|
||||
|
||||
FUNCTION_END();
|
||||
}
|
||||
|
||||
// HandleUnregisterRunner
|
||||
void
|
||||
MessageRunnerManager::HandleUnregisterRunner(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
status_t error = B_OK;
|
||||
// get the parameters
|
||||
int32 token;
|
||||
if (error == B_OK && request->FindInt32("token", &token) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
// find and delete the runner info
|
||||
if (error == B_OK) {
|
||||
if (RunnerInfo *info = _InfoForToken(token))
|
||||
_DeleteInfo(info, false);
|
||||
else
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
// reply to the request
|
||||
if (error == B_OK) {
|
||||
BMessage reply(B_REG_SUCCESS);
|
||||
request->SendReply(&reply);
|
||||
} else {
|
||||
BMessage reply(B_REG_ERROR);
|
||||
reply.AddInt32("error", error);
|
||||
request->SendReply(&reply);
|
||||
}
|
||||
|
||||
FUNCTION_END();
|
||||
}
|
||||
|
||||
// HandleSetRunnerParams
|
||||
void
|
||||
MessageRunnerManager::HandleSetRunnerParams(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
status_t error = B_OK;
|
||||
// get the parameters
|
||||
int32 token;
|
||||
bigtime_t interval;
|
||||
int32 count;
|
||||
bool setInterval = false;
|
||||
bool setCount = false;
|
||||
if (error == B_OK && request->FindInt32("token", &token) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
if (error == B_OK && request->FindInt64("interval", &interval) == B_OK)
|
||||
setInterval = true;
|
||||
if (error == B_OK && request->FindInt32("count", &count) == B_OK)
|
||||
setCount = true;
|
||||
// find the runner info
|
||||
RunnerInfo *info = NULL;
|
||||
if (error == B_OK) {
|
||||
info = _InfoForToken(token);
|
||||
if (!info)
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
// set the new values
|
||||
if (error == B_OK) {
|
||||
bool eventRemoved = false;
|
||||
bool deleteInfo = false;
|
||||
// count
|
||||
if (setCount) {
|
||||
if (count == 0)
|
||||
deleteInfo = true;
|
||||
else
|
||||
info->count = count;
|
||||
}
|
||||
// interval
|
||||
if (setInterval) {
|
||||
eventRemoved = fEventQueue->RemoveEvent(info->event);
|
||||
if (!eventRemoved)
|
||||
info->rescheduled = true;
|
||||
interval = max(interval, kMininalTimeInterval);
|
||||
info->interval = interval;
|
||||
info->time = system_time();
|
||||
if (!_ScheduleEvent(info))
|
||||
error = B_NO_MEMORY; // TODO: The only possible reason?
|
||||
}
|
||||
// remove and delete the info on error
|
||||
if (error != B_OK || deleteInfo)
|
||||
_DeleteInfo(info, eventRemoved);
|
||||
}
|
||||
// reply to the request
|
||||
if (error == B_OK) {
|
||||
BMessage reply(B_REG_SUCCESS);
|
||||
request->SendReply(&reply);
|
||||
} else {
|
||||
BMessage reply(B_REG_ERROR);
|
||||
reply.AddInt32("error", error);
|
||||
request->SendReply(&reply);
|
||||
}
|
||||
|
||||
FUNCTION_END();
|
||||
}
|
||||
|
||||
// HandleGetRunnerInfo
|
||||
void
|
||||
MessageRunnerManager::HandleGetRunnerInfo(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
status_t error = B_OK;
|
||||
// get the parameters
|
||||
int32 token;
|
||||
if (error == B_OK && request->FindInt32("token", &token) != B_OK)
|
||||
error = B_BAD_VALUE;
|
||||
// find the runner info
|
||||
RunnerInfo *info = NULL;
|
||||
if (error == B_OK) {
|
||||
info = _InfoForToken(token);
|
||||
if (!info)
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
// reply to the request
|
||||
if (error == B_OK) {
|
||||
BMessage reply(B_REG_SUCCESS);
|
||||
reply.AddInt64("interval", info->interval);
|
||||
reply.AddInt32("count", info->count);
|
||||
request->SendReply(&reply);
|
||||
} else {
|
||||
BMessage reply(B_REG_ERROR);
|
||||
reply.AddInt32("error", error);
|
||||
request->SendReply(&reply);
|
||||
}
|
||||
|
||||
FUNCTION_END();
|
||||
}
|
||||
|
||||
// Lock
|
||||
bool
|
||||
MessageRunnerManager::Lock()
|
||||
{
|
||||
return fLock.Lock();
|
||||
}
|
||||
|
||||
// Unlock
|
||||
void
|
||||
MessageRunnerManager::Unlock()
|
||||
{
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
// _AddInfo
|
||||
bool
|
||||
MessageRunnerManager::_AddInfo(RunnerInfo *info)
|
||||
{
|
||||
return fRunnerInfos.AddItem(info);
|
||||
}
|
||||
|
||||
// _RemoveInfo
|
||||
bool
|
||||
MessageRunnerManager::_RemoveInfo(RunnerInfo *info)
|
||||
{
|
||||
return fRunnerInfos.RemoveItem(info);
|
||||
}
|
||||
|
||||
// _RemoveInfo
|
||||
MessageRunnerManager::RunnerInfo*
|
||||
MessageRunnerManager::_RemoveInfo(int32 index)
|
||||
{
|
||||
return (RunnerInfo*)fRunnerInfos.RemoveItem(index);
|
||||
}
|
||||
|
||||
// _RemoveInfoWithToken
|
||||
MessageRunnerManager::RunnerInfo*
|
||||
MessageRunnerManager::_RemoveInfoWithToken(int32 token)
|
||||
{
|
||||
RunnerInfo *info = NULL;
|
||||
int32 index = _IndexOfToken(token);
|
||||
if (index >= 0)
|
||||
info = _RemoveInfo(index);
|
||||
return info;
|
||||
}
|
||||
|
||||
// _DeleteInfo
|
||||
bool
|
||||
MessageRunnerManager::_DeleteInfo(RunnerInfo *info, bool eventRemoved)
|
||||
{
|
||||
bool result = _RemoveInfo(info);
|
||||
if (result) {
|
||||
// If the event is not in the event queue and has not been removed
|
||||
// just before, then it is in progress. It will delete itself.
|
||||
if (!eventRemoved && !fEventQueue->RemoveEvent(info->event))
|
||||
info->event = NULL;
|
||||
delete info;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// _CountInfos
|
||||
int32
|
||||
MessageRunnerManager::_CountInfos() const
|
||||
{
|
||||
return fRunnerInfos.CountItems();
|
||||
}
|
||||
|
||||
// _InfoAt
|
||||
MessageRunnerManager::RunnerInfo*
|
||||
MessageRunnerManager::_InfoAt(int32 index) const
|
||||
{
|
||||
return (RunnerInfo*)fRunnerInfos.ItemAt(index);
|
||||
}
|
||||
|
||||
// _InfoForToken
|
||||
MessageRunnerManager::RunnerInfo*
|
||||
MessageRunnerManager::_InfoForToken(int32 token) const
|
||||
{
|
||||
return _InfoAt(_IndexOfToken(token));
|
||||
}
|
||||
|
||||
// _IndexOf
|
||||
int32
|
||||
MessageRunnerManager::_IndexOf(RunnerInfo *info) const
|
||||
{
|
||||
return fRunnerInfos.IndexOf(info);
|
||||
}
|
||||
|
||||
// _IndexOfToken
|
||||
int32
|
||||
MessageRunnerManager::_IndexOfToken(int32 token) const
|
||||
{
|
||||
for (int32 i = 0; RunnerInfo *info = _InfoAt(i); i++) {
|
||||
if (info->token == token)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// _DoEvent
|
||||
bool
|
||||
MessageRunnerManager::_DoEvent(RunnerInfo *info)
|
||||
{
|
||||
FUNCTION_START();
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
bool deleteEvent = false;
|
||||
// first check whether the info does still exist
|
||||
if (_lock.IsLocked() && _IndexOf(info) >= 0) {
|
||||
// If the event has been rescheduled after being removed from the
|
||||
// queue for execution, it needs to be ignored. This may happen, when
|
||||
// the interval is modified.
|
||||
if (info->rescheduled)
|
||||
info->rescheduled = false;
|
||||
else {
|
||||
// send the message
|
||||
bool success = (info->DeliverMessage() == B_OK);
|
||||
// reschedule the event
|
||||
if (success)
|
||||
success = _ScheduleEvent(info);
|
||||
// clean up, if the message delivery of the rescheduling failed
|
||||
if (!success) {
|
||||
deleteEvent = true;
|
||||
info->event = NULL;
|
||||
_RemoveInfo(info);
|
||||
delete info;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The info is no more. That means it had been removed after the
|
||||
// event was removed from the event queue, but before we could acquire
|
||||
// the lock. Simply delete the event.
|
||||
deleteEvent = true;
|
||||
}
|
||||
|
||||
FUNCTION_END();
|
||||
|
||||
return deleteEvent;
|
||||
}
|
||||
|
||||
// _ScheduleEvent
|
||||
bool
|
||||
MessageRunnerManager::_ScheduleEvent(RunnerInfo *info)
|
||||
{
|
||||
bool scheduled = false;
|
||||
// calculate next event time
|
||||
if (info->count != 0) {
|
||||
// avoid a bigtime_t overflow
|
||||
if (LONGLONG_MAX - info->interval < info->time)
|
||||
info->time = LONGLONG_MAX;
|
||||
else
|
||||
info->time += info->interval;
|
||||
info->event->SetTime(info->time);
|
||||
scheduled = fEventQueue->AddEvent(info->event);
|
||||
PRINT(("runner %ld (%lld, %ld) rescheduled: %d, time: %lld, now: %lld\n",
|
||||
info->token, info->interval, info->count, scheduled, info->time, system_time()));
|
||||
}
|
||||
return scheduled;
|
||||
}
|
||||
|
||||
// _NextToken
|
||||
int32
|
||||
MessageRunnerManager::_NextToken()
|
||||
{
|
||||
return fNextToken++;
|
||||
}
|
||||
|
83
src/servers/registrar/MessageRunnerManager.h
Normal file
83
src/servers/registrar/MessageRunnerManager.h
Normal file
@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: MessageRunnerManager.h
|
||||
// Author: Ingo Weinhold (bonefish@users.sf.net)
|
||||
// Description: Manages the registrar side "shadows" of BMessageRunners.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef MESSAGE_RUNNER_MANAGER_H
|
||||
#define MESSAGE_RUNNER_MANAGER_H
|
||||
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
|
||||
class BMessage;
|
||||
class EventQueue;
|
||||
|
||||
class MessageRunnerManager {
|
||||
public:
|
||||
MessageRunnerManager(EventQueue *eventQueue);
|
||||
virtual ~MessageRunnerManager();
|
||||
|
||||
void HandleRegisterRunner(BMessage *request);
|
||||
void HandleUnregisterRunner(BMessage *request);
|
||||
void HandleSetRunnerParams(BMessage *request);
|
||||
void HandleGetRunnerInfo(BMessage *request);
|
||||
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
class RunnerEvent;
|
||||
struct RunnerInfo;
|
||||
friend class RunnerEvent;
|
||||
|
||||
private:
|
||||
bool _AddInfo(RunnerInfo *info);
|
||||
bool _RemoveInfo(RunnerInfo *info);
|
||||
RunnerInfo *_RemoveInfo(int32 index);
|
||||
RunnerInfo *_RemoveInfoWithToken(int32 token);
|
||||
bool _DeleteInfo(RunnerInfo *info, bool eventRemoved);
|
||||
|
||||
int32 _CountInfos() const;
|
||||
|
||||
RunnerInfo *_InfoAt(int32 index) const;
|
||||
RunnerInfo *_InfoForToken(int32 token) const;
|
||||
|
||||
bool _HasInfo(RunnerInfo *info) const;
|
||||
|
||||
int32 _IndexOf(RunnerInfo *info) const;
|
||||
int32 _IndexOfToken(int32 token) const;
|
||||
|
||||
bool _DoEvent(RunnerInfo *info);
|
||||
bool _ScheduleEvent(RunnerInfo *info);
|
||||
|
||||
int32 _NextToken();
|
||||
|
||||
private:
|
||||
BList fRunnerInfos;
|
||||
BLocker fLock;
|
||||
EventQueue *fEventQueue;
|
||||
int32 fNextToken;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_RUNNER_MANAGER_H
|
@ -8,10 +8,14 @@
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
#include "ClipboardHandler.h"
|
||||
#include "EventQueue.h"
|
||||
#include "MessageRunnerManager.h"
|
||||
#include "MIMEManager.h"
|
||||
#include "Registrar.h"
|
||||
#include "TRoster.h"
|
||||
|
||||
static const char *kEventQueueName = "timer_thread";
|
||||
|
||||
/*!
|
||||
\class Registrar
|
||||
\brief The application class of the registrar.
|
||||
@ -26,7 +30,9 @@ Registrar::Registrar()
|
||||
: BApplication(kRegistrarSignature),
|
||||
fRoster(NULL),
|
||||
fClipboardHandler(NULL),
|
||||
fMIMEManager(NULL)
|
||||
fMIMEManager(NULL),
|
||||
fEventQueue(NULL),
|
||||
fMessageRunnerManager(NULL)
|
||||
{
|
||||
FUNCTION_START();
|
||||
}
|
||||
@ -41,6 +47,9 @@ Registrar::~Registrar()
|
||||
{
|
||||
FUNCTION_START();
|
||||
Lock();
|
||||
fEventQueue->Die();
|
||||
delete fMessageRunnerManager;
|
||||
delete fEventQueue;
|
||||
fMIMEManager->Lock();
|
||||
fMIMEManager->Quit();
|
||||
RemoveHandler(fClipboardHandler);
|
||||
@ -59,6 +68,7 @@ Registrar::MessageReceived(BMessage *message)
|
||||
{
|
||||
FUNCTION_START();
|
||||
switch (message->what) {
|
||||
// general requests
|
||||
case B_REG_GET_MIME_MESSENGER:
|
||||
{
|
||||
PRINT(("B_REG_GET_MIME_MESSENGER\n"));
|
||||
@ -77,6 +87,7 @@ Registrar::MessageReceived(BMessage *message)
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
// roster requests
|
||||
case B_REG_ADD_APP:
|
||||
fRoster->HandleAddApplication(message);
|
||||
break;
|
||||
@ -107,6 +118,19 @@ Registrar::MessageReceived(BMessage *message)
|
||||
case B_REG_ACTIVATE_APP:
|
||||
fRoster->HandleActivateApp(message);
|
||||
break;
|
||||
// message runner requests
|
||||
case B_REG_REGISTER_MESSAGE_RUNNER:
|
||||
fMessageRunnerManager->HandleRegisterRunner(message);
|
||||
break;
|
||||
case B_REG_UNREGISTER_MESSAGE_RUNNER:
|
||||
fMessageRunnerManager->HandleUnregisterRunner(message);
|
||||
break;
|
||||
case B_REG_SET_MESSAGE_RUNNER_PARAMS:
|
||||
fMessageRunnerManager->HandleSetRunnerParams(message);
|
||||
break;
|
||||
case B_REG_GET_MESSAGE_RUNNER_INFO:
|
||||
fMessageRunnerManager->HandleGetRunnerInfo(message);
|
||||
break;
|
||||
default:
|
||||
BApplication::MessageReceived(message);
|
||||
break;
|
||||
@ -131,6 +155,9 @@ Registrar::ReadyToRun()
|
||||
// create MIME manager
|
||||
fMIMEManager = new MIMEManager;
|
||||
fMIMEManager->Run();
|
||||
// create message runner manager
|
||||
fEventQueue = new EventQueue(kEventQueueName);
|
||||
fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
|
||||
// init the global be_roster
|
||||
BPrivate::init_registrar_roster(be_app_messenger,
|
||||
BMessenger(NULL, fMIMEManager));
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <Application.h>
|
||||
|
||||
class ClipboardHandler;
|
||||
class EventQueue;
|
||||
class MessageRunnerManager;
|
||||
class MIMEManager;
|
||||
|
||||
namespace BPrivate {
|
||||
@ -45,9 +47,11 @@ public:
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
BPrivate::TRoster *fRoster;
|
||||
ClipboardHandler *fClipboardHandler;
|
||||
MIMEManager *fMIMEManager;
|
||||
BPrivate::TRoster *fRoster;
|
||||
ClipboardHandler *fClipboardHandler;
|
||||
MIMEManager *fMIMEManager;
|
||||
EventQueue *fEventQueue;
|
||||
MessageRunnerManager *fMessageRunnerManager;
|
||||
};
|
||||
|
||||
#endif // REGISTRAR_H
|
||||
|
Loading…
Reference in New Issue
Block a user