Created
July 16, 2009 15:59
-
-
Save gaspard/148495 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Introduction | |
// ============ | |
// | |
// This is the heart of the Metro object: as its 'bang' method is called by a scheduler | |
// the metro object registers the next call in the scheduler with "bang_me_in" method. | |
// Things to know | |
// ============== | |
// | |
// 1. object attributes end with an underscore (run_, tempo_) | |
// 2. the "send" method calls all objects attached to the metro object in the patch (= can take a long time) | |
// 3. ScopedLock and ScopedUnlock are simple C++ classes that help manage locking/unlocking scopes. | |
// Initial methods | |
// =============== | |
/** Reschedule and send a bang. */ | |
void bang(const Value &val) { | |
if (run_) { | |
bang_me_in(ONE_MINUTE / tempo_); | |
send(1, gNilValue); | |
} | |
} | |
/** Send a Value out of an outlet. */ | |
inline void send (size_t port, const Value &val) { | |
if (port > outlets_.size() || port < 1) return; | |
outlets_[port - 1]->send(val); | |
} | |
// THREAD-SAFE versions | |
// ==================== | |
/** Reschedule and send a bang. */ | |
void bang(const Value &val) { | |
ScopedLock lock(mutex_); | |
if (run_) { | |
bang_me_in(ONE_MINUTE / tempo_); | |
send(1, gNilValue); | |
} | |
} | |
/** Send a Value out of an outlet. | |
* This method must be called within a mutex_ lock. | |
*/ | |
inline void send (size_t port, const Value &val) { | |
if (port > outlets_.size() || port < 1) return; | |
Outlet *out = outlets_[port - 1]; | |
// lock "out" | |
ScopedLock lock(out->mutex()); | |
// unlock "metro" during send | |
ScopedUnlock unlock(mutex_); | |
out->send(val); | |
// leaving scope: "metro" lock, "out" unlock | |
} | |
// Order of operations | |
// ========================= | |
// | |
// 1. bang locks 'metro' object (this also protects Outlet "out" from destruction) | |
// 2. the send method: | |
// 2.1 locks the outlet | |
// 2.2 unlocks the 'metro' object | |
// 2.3 sends values | |
// 2.4 locks 'metro' back | |
// 2.5 unlocks the outlet | |
// Questions | |
// ========= | |
// | |
// 1. This implementation is not optimal when "send" is the last operation since we | |
// relock just before unlocking (leaving 'send' .. leaving 'bang') | |
// 2. What is the cost of all these 'lock/unlock' calls ? | |
// 3. Is there a better way to do this ? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment