mirror of
https://github.com/darlinghq/darling-dbuskit.git
synced 2024-11-23 12:19:40 +00:00
ab2546c5b4
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/dbuskit/trunk@32237 72102866-910b-0410-8b05-ffd578937521
265 lines
8.3 KiB
Objective-C
265 lines
8.3 KiB
Objective-C
/** Declaration of DKEndpointManager class that manages D-Bus endpoints.
|
|
Copyright (C) 2011 Free Software Foundation, Inc.
|
|
|
|
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
|
Created: January 2011
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02111 USA.
|
|
*/
|
|
|
|
|
|
#import <Foundation/NSObject.h>
|
|
#include <stdint.h>
|
|
#include <dbus/dbus.h>
|
|
|
|
@class DKEndpoint, DKProxy, NSLock, NSMapTable, NSThread, NSRecursiveLock;
|
|
|
|
|
|
// The structure members should all be of the same size, so the compiler should
|
|
// not do any awkward packing.
|
|
typedef struct {
|
|
id target;
|
|
SEL selector;
|
|
id object;
|
|
intptr_t* returnPointer;
|
|
} DKRingBufferElement;
|
|
|
|
/**
|
|
* DKEndpointManager is a singleton class that maintains a thread to interact
|
|
* with D-Bus. It is responsible for creating and tracking the endpoints to
|
|
* the specific busses and will attempt to recover from connection failures.
|
|
*
|
|
* DKEndpointManager also provides a synchronized mode so that it can be safely
|
|
* called from +initialize methods. In that case, the caller is expected to wrap
|
|
* method calls that might trigger the manager (especially to DKEndpoint,
|
|
* DKPort, DKPortNameServer, DKProxy, or DKNotificationCenter) with calls to
|
|
* -enterInitialize and -leaveInitialize.
|
|
*/
|
|
@interface DKEndpointManager: NSObject
|
|
{
|
|
/**
|
|
* The thread running the runloop which interacts with libdbus.
|
|
*/
|
|
NSThread *workerThread;
|
|
@private
|
|
|
|
/**
|
|
* Tracks whether the thread has been started.
|
|
*/
|
|
BOOL threadStarted;
|
|
|
|
/**
|
|
* Tracks whether we already enabled threading.
|
|
*/
|
|
BOOL threadEnabled;
|
|
|
|
/**
|
|
* Maps active DBusConnections to the corresponding DKEndpoints.
|
|
*/
|
|
NSMapTable *activeConnections;
|
|
|
|
/**
|
|
* Lock to protect changes to the connection tables.
|
|
*/
|
|
NSRecursiveLock *connectionStateLock;
|
|
|
|
/**
|
|
* A (oneway) ring buffer for queuing tuples of the following form:
|
|
* <target, selector, data, pointer-to-return>. The tuples are inserted
|
|
* whenever a libdbus callback requires a value to be returned from the worker
|
|
* thread.
|
|
*/
|
|
DKRingBufferElement *ringBuffer;
|
|
|
|
/**
|
|
* Free-running counter for the producer threads
|
|
*/
|
|
uint32_t producerCounter;
|
|
|
|
/**
|
|
* Since it is possible for more than one thread to write to the ring buffer,
|
|
* it cannot be completely lockless: Producers need to obtain the
|
|
* <ivar>producerLock</ivar> in order to prevent overwriting. Since there is
|
|
* only one consumer thread, it needs no such provisions.
|
|
*/
|
|
NSLock *producerLock;
|
|
|
|
/**
|
|
* Free-running counter for the consumer thread
|
|
*/
|
|
uint32_t consumerCounter;
|
|
|
|
/**
|
|
* Counter to track how many callers are calling into the endpoint-manager
|
|
* from +initialize.
|
|
*/
|
|
NSUInteger initializeRefCount;
|
|
|
|
/**
|
|
* Lock to protect changes to the accounting tables in synchronised mode.
|
|
*/
|
|
NSRecursiveLock *synchronizationStateLock;
|
|
|
|
|
|
/**
|
|
* The <ivar>syncedWatchers</ivar> map table keeps track of watchers that were
|
|
* created while the endpoint manager is in synchronised mode. Each is mapped
|
|
* to the thread it was created in. When the last +initialize call using the
|
|
* manager finishes, the manager will reap these watchers and reschedule them
|
|
* on the worker thread.
|
|
*/
|
|
NSMapTable *syncedWatchers;
|
|
|
|
/**
|
|
* The <ivar>syncedTimers</ivar> map table keeps track of watchers that were
|
|
* created while the endpoint manager is in synchronised mode. Each is mapped
|
|
* to the thread it was created in. When the last +initialize call using the
|
|
* manager finishes, the manager will invalidate these timers and reschedule
|
|
* then on the worker thread.
|
|
*/
|
|
NSMapTable *syncedTimers;
|
|
}
|
|
|
|
/**
|
|
* Returns the shared endpoint manager that is used to manage interactions with
|
|
* libdbus.
|
|
*/
|
|
+ (id)sharedEndpointManager;
|
|
|
|
/**
|
|
* Returns a reference to the worker thread that interacts with D-Bus.
|
|
*/
|
|
- (NSThread*)workerThread;
|
|
|
|
/**
|
|
* Creates or reuses an endpoint.
|
|
*/
|
|
- (id)endpointForDBusConnection: (DBusConnection*)connection
|
|
mergingInfo: (NSDictionary*)info;
|
|
|
|
/**
|
|
* Returns an endpoint connected to an arbitrary address. This is only useful
|
|
* for specific cases where you don't want to use one of the standard message
|
|
* busses. Use -endpointForWellKnownBus: to get a connection for one of those.
|
|
*/
|
|
- (DKEndpoint*)endpointForConnectionTo: (NSString*)address;
|
|
|
|
/**
|
|
* Returns an endpoint connected to one of the well-known message busses as per
|
|
* D-Bus documentation (i.e. DBUS_BUS_SYSTEM, DBUS_BUS_SESSION or
|
|
* DBUS_BUS_STARTER).
|
|
*/
|
|
- (DKEndpoint*)endpointForWellKnownBus: (DBusBusType)type;
|
|
|
|
/**
|
|
* Method to be called by endpoints that are being deallocated.
|
|
*/
|
|
- (void)removeEndpointForDBusConnection: (DBusConnection*)connection;
|
|
|
|
|
|
/**
|
|
* Entry point for the worker thread.
|
|
*/
|
|
- (void)start: (id)ignored;
|
|
|
|
/**
|
|
* Schedules periodic recovery attempts for <var>endpoint/var>. Will be used in
|
|
* case of bus failures. If recovery is successful, <var>aProxy</var> will be
|
|
* notified.
|
|
*/
|
|
- (void)attemptRecoveryForEndpoint: (DKEndpoint*)endpoint
|
|
proxy: (DKProxy*)aProxy;
|
|
|
|
/**
|
|
* Inserts the request into the ring buffer and schedules it for draining in the
|
|
* worker thread. With <var>doWait</var> set to YES this method becomes a
|
|
* synchonisation point: It will spin until the request has completed. This
|
|
* should only be used when a return value is required by the libdbus API.
|
|
*/
|
|
- (BOOL)boolReturnForPerformingSelector: (SEL)selector
|
|
target: (id)target
|
|
data: (void*)data
|
|
waitForReturn: (BOOL)doWait;
|
|
|
|
/**
|
|
* Called from within the worker thread to process requests from the ring
|
|
* buffer.
|
|
*/
|
|
- (void)drainBuffer: (id)ignored;
|
|
|
|
|
|
/**
|
|
* Will be called in order to enable threaded mode.
|
|
*/
|
|
- (void)enableThread;
|
|
|
|
/**
|
|
* Will be called by DBusKit classes that require usage of the bus in their
|
|
* +initialize method.
|
|
*/
|
|
- (void)enterInitialize;
|
|
|
|
/**
|
|
* Will be called by DBusKit classes that require usage of the bus in their
|
|
* +initialize method.
|
|
*/
|
|
- (void)leaveInitialize;
|
|
|
|
/**
|
|
* This method can be used to determine whether the manager is in synchronized
|
|
* mode due to being called from an initialize method.
|
|
*/
|
|
- (BOOL)isSynchronizing;
|
|
|
|
/**
|
|
* This method will be used by instances of <class>DKRunLoopContext</class> to
|
|
* inform the endpoint manager of timers it is presently using. If the manager
|
|
* is in synchronized mode (i.e. being called from +initialize), a reference to
|
|
* the timer will be tracked until it either no longer needed or has
|
|
* successfully been rescheduled on the worker thread. In order to track all
|
|
* data required, the <var>context</var> the timer comes from must be specified.
|
|
*/
|
|
- (void)registerTimer: (id)timer
|
|
fromContext: (id)context;
|
|
|
|
/**
|
|
* This method will be used by instances of <class>DKRunLoopContext</class> to
|
|
* inform the endpoint manager of <class>DKWatcher</class> instances it is
|
|
* presently using to monitor file descriptors on behalf of libdbus. If the manager
|
|
* is in synchronized mode (i.e. being called from +initialize), a reference to
|
|
* the watcher will be tracked until it either no longer needed or has
|
|
* successfully been rescheduled on the worker thread.
|
|
*/
|
|
- (void)registerWatcher: (id)watcher;
|
|
|
|
/**
|
|
* If the receiver is in synchronized mode, this removes the reference to the
|
|
* timer object.
|
|
*/
|
|
- (void)unregisterTimer: (id)timer;
|
|
|
|
/**
|
|
* If the receiver is in synchronized mode, this removes the reference to the
|
|
* watcher object.
|
|
*/
|
|
- (void)unregisterWatcher: (id)watcher;
|
|
@end
|
|
|
|
/**
|
|
* Macro to check whether the code is presently executing in the worker thread
|
|
*/
|
|
#define DKInWorkerThread (BOOL)[[[DKEndpointManager sharedEndpointManager] workerThread] isEqual: [NSThread currentThread]];
|