Skip to content

Instantly share code, notes, and snippets.

@gaspard
Created July 16, 2009 15:59
Show Gist options
  • Save gaspard/148495 to your computer and use it in GitHub Desktop.
Save gaspard/148495 to your computer and use it in GitHub Desktop.
// 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