… | |
… | |
2078 | is that the author does not know of a simple (or any) algorithm for a |
2078 | is that the author does not know of a simple (or any) algorithm for a |
2079 | multiple-writer-single-reader queue that works in all cases and doesn't |
2079 | multiple-writer-single-reader queue that works in all cases and doesn't |
2080 | need elaborate support such as pthreads. |
2080 | need elaborate support such as pthreads. |
2081 | |
2081 | |
2082 | That means that if you want to queue data, you have to provide your own |
2082 | That means that if you want to queue data, you have to provide your own |
2083 | queue. And here is how you would implement locking: |
2083 | queue. But at least I can tell you would implement locking around your |
|
|
2084 | queue: |
2084 | |
2085 | |
2085 | =over 4 |
2086 | =over 4 |
2086 | |
2087 | |
2087 | =item queueing from a signal handler context |
2088 | =item queueing from a signal handler context |
2088 | |
2089 | |
… | |
… | |
2125 | |
2126 | |
2126 | =item queueing from a thread context |
2127 | =item queueing from a thread context |
2127 | |
2128 | |
2128 | The strategy for threads is different, as you cannot (easily) block |
2129 | The strategy for threads is different, as you cannot (easily) block |
2129 | threads but you can easily preempt them, so to queue safely you need to |
2130 | threads but you can easily preempt them, so to queue safely you need to |
2130 | emply a traditional mutex lock, such as in this pthread example: |
2131 | employ a traditional mutex lock, such as in this pthread example: |
2131 | |
2132 | |
2132 | static ev_async mysig; |
2133 | static ev_async mysig; |
2133 | static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; |
2134 | static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; |
2134 | |
2135 | |
2135 | static void |
2136 | static void |
… | |
… | |
2912 | =item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers) |
2913 | =item Changing timer/periodic watchers (by autorepeat or calling again): O(log skipped_other_timers) |
2913 | |
2914 | |
2914 | That means that changing a timer costs less than removing/adding them |
2915 | That means that changing a timer costs less than removing/adding them |
2915 | as only the relative motion in the event queue has to be paid for. |
2916 | as only the relative motion in the event queue has to be paid for. |
2916 | |
2917 | |
2917 | =item Starting io/check/prepare/idle/signal/child watchers: O(1) |
2918 | =item Starting io/check/prepare/idle/signal/child/fork/async watchers: O(1) |
2918 | |
2919 | |
2919 | These just add the watcher into an array or at the head of a list. |
2920 | These just add the watcher into an array or at the head of a list. |
2920 | |
2921 | |
2921 | =item Stopping check/prepare/idle watchers: O(1) |
2922 | =item Stopping check/prepare/idle/fork/async watchers: O(1) |
2922 | |
2923 | |
2923 | =item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE)) |
2924 | =item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE)) |
2924 | |
2925 | |
2925 | These watchers are stored in lists then need to be walked to find the |
2926 | These watchers are stored in lists then need to be walked to find the |
2926 | correct watcher to remove. The lists are usually short (you don't usually |
2927 | correct watcher to remove. The lists are usually short (you don't usually |
… | |
… | |
2942 | =item Priority handling: O(number_of_priorities) |
2943 | =item Priority handling: O(number_of_priorities) |
2943 | |
2944 | |
2944 | Priorities are implemented by allocating some space for each |
2945 | Priorities are implemented by allocating some space for each |
2945 | priority. When doing priority-based operations, libev usually has to |
2946 | priority. When doing priority-based operations, libev usually has to |
2946 | linearly search all the priorities, but starting/stopping and activating |
2947 | linearly search all the priorities, but starting/stopping and activating |
2947 | watchers becomes O(1) w.r.t. prioritiy handling. |
2948 | watchers becomes O(1) w.r.t. priority handling. |
|
|
2949 | |
|
|
2950 | =item Sending an ev_async: O(1) |
|
|
2951 | |
|
|
2952 | =item Processing ev_async_send: O(number_of_async_watchers) |
|
|
2953 | |
|
|
2954 | =item Processing signals: O(max_signal_number) |
|
|
2955 | |
|
|
2956 | Sending involves a syscall I<iff> there were no other C<ev_async_send> |
|
|
2957 | calls in the current loop iteration. Checking for async and signal events |
|
|
2958 | involves iterating over all running async watchers or all signal numbers. |
2948 | |
2959 | |
2949 | =back |
2960 | =back |
2950 | |
2961 | |
2951 | |
2962 | |
2952 | =head1 Win32 platform limitations and workarounds |
2963 | =head1 Win32 platform limitations and workarounds |