#include <sthread.h>
class sthread_base_t : public w_base_t {
public:
typedef uint4_t id_t;
enum {
max_thread = 32,
WAIT_IMMEDIATE = 0,
// sthreads package recognizes 2 WAIT_* values:
// == WAIT_IMMEDIATE
// and != WAIT_IMMEDIATE.
// If it's not WAIT_IMMEDIATE, it's assumed to be
// a positive integer (milliseconds) used for the
// select timeout.
//
// All other WAIT_* values other than WAIT_IMMEDIATE
// are handled by sm layer.
//
// The user of the thread (e.g., sm) had better
// convert timeouts that are negative values (WAIT_* below)
// to something >= 0 before calling block().
//
//
WAIT_FOREVER = -1,
WAIT_ANY = -2,
WAIT_ALL = -3,
WAIT_SPECIFIED_BY_THREAD = -4, // used by lock manager
WAIT_SPECIFIED_BY_XCT = -5, // used by lock manager
stack_sz = (1024 * 64)
};
#include "st_error.h"
enum {
stOS = fcOS,
stINTERNAL = fcINTERNAL,
stNOTIMPLEMENTED = fcNOTIMPLEMENTED,
};
};
#define NAME_ARRAY 64
class sthread_name_t {
public:
void rename(const char *n1, const char *n2=0, const char *n3=0);
NORET sthread_name_t();
NORET ~sthread_name_t();
char _name[NAME_ARRAY];
NORET W_FASTNEW_CLASS_DECL;
};
class sthread_named_base_t: public sthread_base_t {
public:
NORET sthread_named_base_t(
const char* n1 = 0,
const char* n2 = 0,
const char* n3 = 0);
NORET ~sthread_named_base_t();
void rename(
const char* n1,
const char* n2 = 0,
const char* n3 = 0);
const char* name() const;
void unname();
};
/*
* Thread Structure
*/
class sthread_t : public sthread_named_base_t {
public:
enum status_t {
t_defunct, // status before and after run()
t_ready, // status when entering run()
t_running, // when me() is this thread
t_blocked, // thread is blocked on anything
};
enum priority_t {
t_time_critical = 3,
t_regular = 2,
t_fixed_low = 1,
t_idle_time = 0,
max_priority = t_time_critical,
min_priority = t_idle_time
};
void* user; // user can use this
const id_t id;
int trace_level; // for debugging
/*
* Thread Control
*/
static w_rc_t block(
int4_t timeout = WAIT_FOREVER,
sthread_list_t* list = 0,
const char* const caller = 0);
static void yield(bool doselect=false);
w_rc_t unblock(const w_rc_t& rc = *(w_rc_t*)0);
static void end();
static void dump(const char *, ostream &);
w_rc_t set_priority(priority_t priority);
priority_t priority() const;
status_t status() const;
w_rc_t set_use_float(int);
void push_resource_alloc(const char* n);
void pop_resource_alloc();
/*
* Asynchronous I/O ops
*/
static char* set_bufsize(int size);
static w_rc_t open(
const char* path,
int flags,
int mode,
int& fd);
static w_rc_t close(int fd);
static w_rc_t writev(
int fd,
const iovec* iov,
size_t iovcnt);
static w_rc_t write(
int fd,
const void* buf,
int n);
static w_rc_t read(
int fd,
const void* buf,
int n);
static w_rc_t readv(
int fd,
const iovec* iov,
size_t iovcnt);
static w_rc_t lseek(
int fd,
off_t offset,
int whence,
off_t& ret);
static w_rc_t fsync(int fd);
/*
* Misc
*/
static sthread_t* me() { return _me; }
void sleep(long timeout = WAIT_FOREVER);
w_rc_t wait(long timeout = WAIT_FOREVER);
static void set_diskrw_name(const char* diskrw)
{_diskrw = diskrw;}
friend ostream& operator<<(
ostream& o,
const sthread_t& t);
protected:
NORET sthread_t(
priority_t priority = t_regular,
bool block_immediate = false,
bool auto_delete = false,
const char* name = 0);
virtual NORET ~sthread_t();
virtual void run() = 0;
};
The thread mechanism allows several threads of control to share the same address space. Each thread is represented by an instance of class sthread_t. Once created, a thread is an independent entity with its own stack. A thread's execution begins with its run method and ends when run returns. A thread can also be made to end early by calling end, which forces a longjmp out of the run method.
In a C++ program, the sthread initialization code is built into the library such it will execute before the main function. The initialization code is responsible for spawning a main_thread, such that, when the initialization function returns, it returns in the context of the main_thread. This ensures that the program executes in a threaded environment from the very beginning.
Class sthread_base_t is the base class for all sthread classes. It defines constants and enums used throughout the thread package.
Class sthread_named_base_t inherits from sthread_base_t and adds a name string to the class. Its only purpose is to ease debugging by providing a name to sthread classes.
Class sthread_t is an abstract base class that represents a thread of execution; it must be derived in order to be used, hence the protected constructor.
enum status_t
t_defunct is dead t_ready is in the ready queue waiting to run t_running is running t_blocked is not ready to run
enum priority_t
t_time_critical has highest priority t_regular has regular priority t_fixed_low has lower than regular priority t_idle_time only runs when system is idle
sthread_t(priority, block_immediate, auto_delete, name)
~sthread_t()
run()
static end()
static block(timeout, list, caller)
unblock(rc)
static me()
wait(timeout)
sleep(timeout)
yield()
Sthread_t provides methods similar to Unix in handling file I/O. However, the file descriptors used by these methods are not interchangeable with that of Unix, i.e., the fd returned by sthread_t::open can only be used with other methods in sthread_t such as sthread_t::read.
These I/O operations are closely integrated with buffer pool management. The storage manager buffer pool is located in memory shared with the diskrw processes. I/O requests must refer to locations in this shared memory.
Now that most popular operating systems provide threads and asynchronous I/O, the sthread_t I/O operations should be re-implemented or even eliminated.