/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// Platform independent WaitBarrier API. // An armed WaitBarrier prevents threads from advancing until the threads are // woken by calling disarm(). The barrier is armed by setting a non-zero value // - the tag. When the WaitBarrier is created, a thread is designated the owner // and is the thread that should arm and disarm the WaitBarrier. In debug builds // this is enforced. // // Expected Usage: // - Arming thread: // tag = ...; // non-zero value // barrier.arm(tag); // <publish tag> // <work> // barrier.disarm(); // // - After arm(tag) returns any thread calling wait(tag) will block. // - Calling disarm() guarantees any thread calling or that has wait(tag) will // return. Either they will see the WaitBarrier as disarmed or they will be // unblocked and eligible to execute again when disarm() returns. // - After calling disarm() the barrier is ready to be re-armed with a new tag. // (may not be re-armed with last used tag) // // - Waiting threads // wait(tag); // don't execute following code unless 'safe' // <work> // // - A call to wait(tag) will block if the barrier is armed with the value // 'tag'; else it will return immediately. // - A blocked thread is eligible to execute again once the barrier is // disarmed when disarm() has been called. // // It is a usage error to: // - call arm on a barrier that is already armed // - call disarm on a barrier that is not armed // - arm with the same tag as last used // Usage errors are checked in debug builds but may be ignored otherwise. // // A primary goal of the WaitBarrier implementation is to wake all waiting // threads as fast, and as concurrently, as possible. // template <typename WaitBarrierImpl> class WaitBarrierType : public CHeapObj<mtInternal> {
WaitBarrierImpl _impl;
NONCOPYABLE(WaitBarrierType);
#ifdef ASSERT int _last_arm_tag;
Thread* _owner; #endif
// Guarantees any thread calling wait() with same tag will be blocked. // Provides a trailing fence. void arm(int barrier_tag) { #ifdef ASSERT
assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
_last_arm_tag = barrier_tag;
assert(_owner == Thread::current(), "Not owner thread"); #endif
_impl.arm(barrier_tag);
}
// Guarantees any thread that called wait() will be awake when it returns. // Provides a trailing fence. void disarm() {
assert(_owner == Thread::current(), "Not owner thread");
_impl.disarm();
}
// Guarantees not to return until disarm() is called, // if called with currently armed tag (otherwise returns immediately). // Implementations must guarantee no spurious wakeups. // Provides a trailing fence. void wait(int barrier_tag) {
assert(_owner != Thread::current(), "Trying to wait with owner thread");
_impl.wait(barrier_tag);
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.