|
#ifndef GREENLET_THREAD_STATE_CREATOR_HPP |
|
#define GREENLET_THREAD_STATE_CREATOR_HPP |
|
|
|
#include <ctime> |
|
#include <stdexcept> |
|
|
|
#include "greenlet_internal.hpp" |
|
#include "greenlet_refs.hpp" |
|
#include "greenlet_thread_support.hpp" |
|
|
|
#include "TThreadState.hpp" |
|
|
|
namespace greenlet { |
|
|
|
|
|
typedef void (*ThreadStateDestructor)(ThreadState* const); |
|
|
|
template<ThreadStateDestructor Destructor> |
|
class ThreadStateCreator |
|
{ |
|
private: |
|
|
|
|
|
ThreadState* _state; |
|
G_NO_COPIES_OF_CLS(ThreadStateCreator); |
|
|
|
inline bool has_initialized_state() const noexcept |
|
{ |
|
return this->_state != (ThreadState*)1; |
|
} |
|
|
|
inline bool has_state() const noexcept |
|
{ |
|
return this->has_initialized_state() && this->_state != nullptr; |
|
} |
|
|
|
public: |
|
|
|
|
|
|
|
ThreadStateCreator() : |
|
_state((ThreadState*)1) |
|
{ |
|
} |
|
|
|
~ThreadStateCreator() |
|
{ |
|
if (this->has_state()) { |
|
Destructor(this->_state); |
|
} |
|
|
|
this->_state = nullptr; |
|
} |
|
|
|
inline ThreadState& state() |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!this->has_initialized_state()) { |
|
|
|
this->_state = new ThreadState; |
|
|
|
|
|
|
|
|
|
} |
|
if (!this->_state) { |
|
throw std::runtime_error("Accessing state after destruction."); |
|
} |
|
return *this->_state; |
|
} |
|
|
|
operator ThreadState&() |
|
{ |
|
return this->state(); |
|
} |
|
|
|
operator ThreadState*() |
|
{ |
|
return &this->state(); |
|
} |
|
|
|
inline int tp_traverse(visitproc visit, void* arg) |
|
{ |
|
if (this->has_state()) { |
|
return this->_state->tp_traverse(visit, arg); |
|
} |
|
return 0; |
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
}; |
|
|
|
#endif |
|
|