Class: Lich::Common::DetachableClientRegistry

Inherits:
Object
  • Object
show all
Defined in:
documented/common/detachable_client_registry.rb

Overview

Thread-safe registry for clients sharing one detachable listener.

Instance Method Summary collapse

Constructor Details

#initializeDetachableClientRegistry

Initializes the registry with an empty client list and mutex for thread safety.



10
11
12
13
# File 'documented/common/detachable_client_registry.rb', line 10

def initialize
  @clients = []
  @mutex = Mutex.new
end

Instance Method Details

#countInteger

Returns the number of registered clients.

Returns:

  • (Integer)

    the count of clients



79
80
81
# File 'documented/common/detachable_client_registry.rb', line 79

def count
  @mutex.synchronize { @clients.length }
end

#empty?Boolean

Returns whether the registry has no registered clients.

Returns:

  • (Boolean)

    true if the client list is empty, false otherwise



86
87
88
# File 'documented/common/detachable_client_registry.rb', line 86

def empty?
  @mutex.synchronize { @clients.empty? }
end

#primaryObject?

Returns the first registered client, or nil if the registry is empty.

The primary client is the earliest registered; subsequent clients are considered secondary listeners. This is thread-safe.

Returns:

  • (Object, nil)

    the primary client, or nil if no clients are registered



62
63
64
# File 'documented/common/detachable_client_registry.rb', line 62

def primary
  @mutex.synchronize { @clients.first }
end

#primary?(client) ⇒ Boolean

Returns whether the given client is the primary (first registered) client.

Uses identity comparison, not equality. This is thread-safe.

Parameters:

  • client (Object)

    the client to check

Returns:

  • (Boolean)

    true if the client is the first registered client, false otherwise



72
73
74
# File 'documented/common/detachable_client_registry.rb', line 72

def primary?(client)
  @mutex.synchronize { @clients.first.equal?(client) }
end

#register(client) ⇒ Boolean

Registers a client with the registry, returning whether this is the first client.

If the client is already registered, it is not added again. Clients are stored in registration order. The registry is thread-safe via a mutex.

Examples:

registry = DetachableClientRegistry.new
registry.register(client1) #=> true
registry.register(client2) #=> false
registry.register(client1) #=> false (already registered)

Parameters:

  • client (Object)

    the client to register

Returns:

  • (Boolean)

    true if the registry transitioned from empty to non-empty, false otherwise



27
28
29
30
31
32
33
# File 'documented/common/detachable_client_registry.rb', line 27

def register(client)
  @mutex.synchronize do
    was_empty = @clients.empty?
    @clients << client unless @clients.include?(client)
    was_empty && !@clients.empty?
  end
end

#remove_allArray

Removes all registered clients and returns the removed list.

This atomically clears the registry and returns the clients that were removed. This is thread-safe.

Returns:

  • (Array)

    the list of clients that were removed



96
97
98
99
100
101
102
# File 'documented/common/detachable_client_registry.rb', line 96

def remove_all
  @mutex.synchronize do
    clients = @clients.dup
    @clients.clear
    clients
  end
end

#snapshotArray

Returns a copy of the current client list.

This is thread-safe and safe to iterate over without holding the mutex.

Examples:

clients = registry.snapshot
clients.each { |client| client.notify }

Returns:

  • (Array)

    a duplicate of the client list



52
53
54
# File 'documented/common/detachable_client_registry.rb', line 52

def snapshot
  @mutex.synchronize { @clients.dup }
end

#unregister(client) ⇒ Object

Returns whether the client was removed and whether the registry is now empty. The pair lets lifecycle reporting happen outside the mutex.



37
38
39
40
41
42
# File 'documented/common/detachable_client_registry.rb', line 37

def unregister(client)
  @mutex.synchronize do
    removed = !@clients.delete(client).nil?
    [removed, @clients.empty?]
  end
end