# Path: coilmq/util/concurrency.py
# def synchronized(lock):
#     def synchronize(func):
#         """
#         Decorator to lock and unlock a method (Phillip J. Eby).
# 
#         This function is to be used with object instance methods; the object must
#         have a _lock variable (of type C{threading.Lock} or C{threading.RLock}).
# 
#         @param func: Method to decorate
#         @type func: C{callable}
#         """
#         @functools.wraps(func)
#         def wrapper(*args, **kwargs):
#             with lock:
#                 return func(*args, **kwargs)
#         return wrapper
#     return synchronize


import logging
import threading
import uuid
from collections import defaultdict
from coilmq.util.concurrency import synchronized

lock = threading.RLock()


class TopicManager(object):
    """
    Class that manages distribution of messages to topic subscribers.

    This class uses C{threading.RLock} to guard the public methods.  This is probably
    a bit excessive, given 1) the actomic nature of basic C{dict} read/write operations 
    and  2) the fact that most of the internal data structures are keying off of the 
    STOMP connection, which is going to be thread-isolated.  That said, this seems like 
    the technically correct approach and should increase the chance of this code being
    portable to non-GIL systems.

    @ivar _topics: A dict of registered topics, keyed by destination.
    @type _topics: C{dict} of C{str} to C{set} of L{coilmq.server.StompConnection}
    """

    def __init__(self):
        self.log = logging.getLogger(
            '%s.%s' % (__name__, self.__class__.__name__))

        # Lock var is required for L{synchornized} decorator.
        self._lock = threading.RLock()

        self._topics = defaultdict(set)

        # TODO: If we want durable topics, we'll need a store for topics.


# Path: coilmq/util/concurrency.py
# def synchronized(lock):
#     def synchronize(func):
#         """
#         Decorator to lock and unlock a method (Phillip J. Eby).
# 
#         This function is to be used with object instance methods; the object must
#         have a _lock variable (of type C{threading.Lock} or C{threading.RLock}).
# 
#         @param func: Method to decorate
#         @type func: C{callable}
#         """
#         @functools.wraps(func)
#         def wrapper(*args, **kwargs):
#             with lock:
#                 return func(*args, **kwargs)
#         return wrapper
#     return synchronize


# Path: coilmq/topic.py
import logging
import threading
import uuid
from collections import defaultdict
from coilmq.util.concurrency import synchronized


lock = threading.RLock()


class TopicManager(object):
    """
    Class that manages distribution of messages to topic subscribers.

    This class uses C{threading.RLock} to guard the public methods.  This is probably
    a bit excessive, given 1) the actomic nature of basic C{dict} read/write operations 
    and  2) the fact that most of the internal data structures are keying off of the 
    STOMP connection, which is going to be thread-isolated.  That said, this seems like 
    the technically correct approach and should increase the chance of this code being
    portable to non-GIL systems.

    @ivar _topics: A dict of registered topics, keyed by destination.
    @type _topics: C{dict} of C{str} to C{set} of L{coilmq.server.StompConnection}
    """

    def __init__(self):
        self.log = logging.getLogger(
            '%s.%s' % (__name__, self.__class__.__name__))

        # Lock var is required for L{synchornized} decorator.
        self._lock = threading.RLock()

        self._topics = defaultdict(set)

        # TODO: If we want durable topics, we'll need a store for topics.


    @synchronized(lock)