123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- // gold-threads.h -- thread support for gold -*- C++ -*-
- // Copyright (C) 2006-2015 Free Software Foundation, Inc.
- // Written by Ian Lance Taylor <iant@google.com>.
- // This file is part of gold.
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 3 of the License, or
- // (at your option) any later version.
- // 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 General Public License for more details.
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- // MA 02110-1301, USA.
- // gold can be configured to support threads. If threads are
- // supported, the user can specify at runtime whether or not to
- // support them. This provides an interface to manage locking
- // accordingly.
- // Lock
- // A simple lock class.
- #ifndef GOLD_THREADS_H
- #define GOLD_THREADS_H
- namespace gold
- {
- class Condvar;
- class Once_initialize;
- class Initialize_lock_once;
- // The interface for the implementation of a Lock.
- class Lock_impl
- {
- public:
- Lock_impl()
- { }
- virtual
- ~Lock_impl()
- { }
- virtual void
- acquire() = 0;
- virtual void
- release() = 0;
- };
- // A simple lock class.
- class Lock
- {
- public:
- Lock();
- ~Lock();
- // Acquire the lock.
- void
- acquire()
- { this->lock_->acquire(); }
- // Release the lock.
- void
- release()
- { this->lock_->release(); }
- private:
- // This class can not be copied.
- Lock(const Lock&);
- Lock& operator=(const Lock&);
- friend class Condvar;
- Lock_impl*
- get_impl() const
- { return this->lock_; }
- Lock_impl* lock_;
- };
- // RAII for Lock.
- class Hold_lock
- {
- public:
- Hold_lock(Lock& lock)
- : lock_(lock)
- { this->lock_.acquire(); }
- ~Hold_lock()
- { this->lock_.release(); }
- private:
- // This class can not be copied.
- Hold_lock(const Hold_lock&);
- Hold_lock& operator=(const Hold_lock&);
- Lock& lock_;
- };
- class Hold_optional_lock
- {
- public:
- Hold_optional_lock(Lock* lock)
- : lock_(lock)
- {
- if (this->lock_ != NULL)
- this->lock_->acquire();
- }
- ~Hold_optional_lock()
- {
- if (this->lock_ != NULL)
- this->lock_->release();
- }
- private:
- Hold_optional_lock(const Hold_optional_lock&);
- Hold_optional_lock& operator=(const Hold_optional_lock&);
- Lock* lock_;
- };
- // The interface for the implementation of a condition variable.
- class Condvar_impl
- {
- public:
- Condvar_impl()
- { }
- virtual
- ~Condvar_impl()
- { }
- virtual void
- wait(Lock_impl*) = 0;
- virtual void
- signal() = 0;
- virtual void
- broadcast() = 0;
- };
- // A simple condition variable class. It is always associated with a
- // specific lock.
- class Condvar
- {
- public:
- Condvar(Lock& lock);
- ~Condvar();
- // Wait for the condition variable to be signalled. This should
- // only be called when the lock is held.
- void
- wait()
- { this->condvar_->wait(this->lock_.get_impl()); }
- // Signal the condition variable--wake up at least one thread
- // waiting on the condition variable. This should only be called
- // when the lock is held.
- void
- signal()
- { this->condvar_->signal(); }
- // Broadcast the condition variable--wake up all threads waiting on
- // the condition variable. This should only be called when the lock
- // is held.
- void
- broadcast()
- { this->condvar_->broadcast(); }
- private:
- // This class can not be copied.
- Condvar(const Condvar&);
- Condvar& operator=(const Condvar&);
- Lock& lock_;
- Condvar_impl* condvar_;
- };
- // A class used to do something once. This is an abstract parent
- // class; any actual use will involve a child of this.
- class Once
- {
- public:
- Once();
- virtual
- ~Once()
- { }
- // Call this function to do whatever it is. We pass an argument
- // even though you have to use a child class because in some uses
- // setting the argument would itself require a Once class.
- void
- run_once(void* arg);
- // This is an internal function, which must be public because it is
- // run by an extern "C" function called via pthread_once.
- void
- internal_run(void* arg);
- protected:
- // This must be implemented by the child class.
- virtual void
- do_run_once(void* arg) = 0;
- private:
- // True if we have already run the function.
- bool was_run_;
- #if defined(ENABLE_THREADS) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
- // Internal compare-and-swap lock on was_run_;
- uint32_t was_run_lock_;
- #endif
- // The lock to run the function only once.
- Once_initialize* once_;
- };
- // A class used to initialize a lock exactly once, after the options
- // have been read. This is needed because the implementation of locks
- // depends on whether we've seen the --threads option. Before the
- // options have been read, we know we are single-threaded, so we can
- // get by without using a lock. This class should be an instance
- // variable of the class which has a lock which needs to be
- // initialized.
- class Initialize_lock : public Once
- {
- public:
- // The class which uses this will have a pointer to a lock. This
- // must be constructed with a pointer to that pointer.
- Initialize_lock(Lock** pplock)
- : pplock_(pplock)
- { }
- // Initialize the lock. Return true if the lock is now initialized,
- // false if it is not (because the options have not yet been read).
- bool
- initialize();
- protected:
- void
- do_run_once(void*);
- private:
- // A pointer to the lock pointer which must be initialized.
- Lock** const pplock_;
- };
- } // End namespace gold.
- #endif // !defined(GOLD_THREADS_H)
|