// synchronization.h /* Copyright 2010 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #pragma once #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/mutex.h" #include "mongo/util/concurrency/mutex.h" namespace mongo { /** * Type of callback functions that can be invoked when markThreadIdle() runs. * These functions *must not throw*. */ typedef void (*ThreadIdleCallback)(); /** * Informs the registered listener that this thread believes it may go idle for an extended * period. The caller should avoid calling markThreadIdle at a high rate, as it can both be * moderately costly itself and in terms of distributed overhead for subsequent malloc/free * calls. */ void markThreadIdle(); /** * Allows for registering callbacks for when threads go idle and become active. This is used * by TCMalloc to return freed memory to its central freelist at appropriate points, so it * won't happen during critical sections while holding locks. Calling this is not thread-safe. */ void registerThreadIdleCallback(ThreadIdleCallback callback); /* * A class to establish a synchronization point between two threads. One thread is the waiter * and one is the notifier. After the notification event, both proceed normally. * * This class is thread-safe. */ class Notification { MONGO_DISALLOW_COPYING(Notification); public: Notification(); /* * Blocks until the method 'notifyOne()' is called. */ void waitToBeNotified(); /* * Notifies the waiter of '*this' that it can proceed. Can only be called once. */ void notifyOne(); private: stdx::mutex _mutex; // protects state below unsigned long long lookFor; unsigned long long cur; stdx::condition_variable _condition; // cond over _notified being true }; /** establishes a synchronization point between threads. N threads are waits and one is notifier. threadsafe. */ class NotifyAll { MONGO_DISALLOW_COPYING(NotifyAll); public: NotifyAll(); typedef unsigned long long When; When now(); /** awaits the next notifyAll() call by another thread. notifications that precede this call are ignored -- we are looking for a fresh event. */ void waitFor(When); /** a bit faster than waitFor( now() ) */ void awaitBeyondNow(); /** may be called multiple times. notifies all waiters */ void notifyAll(When); /** indicates how many threads are waiting for a notify. */ unsigned nWaiting() const { return _nWaiting; } private: stdx::mutex _mutex; stdx::condition_variable _condition; When _lastDone; When _lastReturned; unsigned _nWaiting; }; } // namespace mongo