• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15 
16 #include <atomic>         // for atomic_int
17 #include <unordered_map>  // for unordere...
18 
19 #include "aemu/base/synchronization/ConditionVariable.h"  // for Conditio...
20 #include "aemu/base/synchronization/Lock.h"               // for Lock
21 #include "aemu/base/synchronization/MessageChannel.h"     // for MessageC...
22 
23 namespace android {
24 namespace base {
25 
26 typedef void (*MessageAvailableCallback)(void* opaque);
27 
28 // A CallbackRegistry can be used to (un)register callbacks, the callbacks
29 // are invoked when the invokeCallbacks is called. A callback is guaranteed
30 // never to be called once unregisterCallback is returned.
31 //
32 // The expectation is that the invokeCallbacks method is called relatively
33 // frequently, since registration only really happens when this method is
34 // invoked. Unregister can block if processing is currently take place to
35 // guarantee that a callback is never called once unregisterCallback returns.
36 //
37 // Only one thread can be actively processing invokeCallbacks, other threads
38 // will block and wait until invokeCallbacks has completed.
39 //
40 // The MessageAvailableCallback functions should not block too long, as this can
41 // cause blocking on the unregister method and invokeCallbacks.
42 //
43 // It is expected that registration and procesessing happen on
44 // two separate threads.
45 class CallbackRegistry {
46 public:
47     CallbackRegistry() = default;
48     ~CallbackRegistry();
49 
50     // Registers the given callback under the `opaque` key. This does not block,
51     // unless the registration queue is filled up. |messageAvailable| Callback
52     // to register. |opaque| Key under which this callback is registered.
53     void registerCallback(MessageAvailableCallback messageAvailable,
54                           void* opaque);
55 
56     // Unregister the callback identiefied by the `opaque` key. You are
57     // guaranteed that the associated callback will not be invoked after this
58     // function returns. This call  can block if:
59     // - processing is currently taking place.
60     // - the message queue is filled to capacity.
61     //
62     // You can safely delete opaque upon return.
63     //
64     // |opaque| Key under which this callback is registered.
65     void unregisterCallback(void* opaque);
66 
67     // This will process all the registrations and invoke the callbacks.
68     void invokeCallbacks();
69 
70     // Close the registry, cancelling any pending registrations.
71     void close();
72 
73     // Number of register/unregister slots available before blocking.
74     // (Mainly used by unit tests to make sure we do not overrun the queue)
75     size_t available();
76 
77     // Maximum number of slots
max_slots()78     size_t max_slots() { return MAX_QUEUE_SIZE; };
79 
80     // true if we are currently processing requests.
processing()81     bool processing() { return mProcessing; }
82 
83 private:
84     enum MessageForwarderCommand {
85         MESSAGE_FORWARDER_ADD = 0,
86         MESSAGE_FORWARDER_REMOVE = 1,
87         MESSAGE_UNKNOWN = 2,
88     };
89 
90     struct ForwarderMessage {
91         MessageForwarderCommand cmd;
92         void* data;
93         MessageAvailableCallback callback;
94     };
95 
96     void updateForwarders();
97 
98     static const size_t MAX_QUEUE_SIZE = 64;
99     android::base::MessageChannel<ForwarderMessage, MAX_QUEUE_SIZE> mMessages;
100     android::base::Lock mLock;            // protects mStoredForwarders
101     android::base::Lock mProcessingLock;  // protects processing.
102     android::base::ConditionVariable mCvRemoval;
103     std::unordered_map<void*, MessageAvailableCallback> mStoredForwarders;
104     bool mProcessing{false};
105 };
106 
107 }  // namespace base
108 }  // namespace android
109