Added core classes.
This commit is contained in:
parent
a68c6b6230
commit
b351b417fd
26 changed files with 793 additions and 0 deletions
19
env/assert.cpp
vendored
Normal file
19
env/assert.cpp
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "assert.hpp"
|
||||
|
||||
#include "../std/iostream.hpp"
|
||||
|
||||
#include <cassert> // for assert
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
void FireAssert(SourceAddress const & sa, string const & msg)
|
||||
{
|
||||
cerr << sa.ToString() << msg << endl;
|
||||
#ifdef DEBUG
|
||||
assert(false);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
}
|
18
env/assert.hpp
vendored
Normal file
18
env/assert.hpp
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "message_list.hpp"
|
||||
#include "source_address.hpp"
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
void FireAssert(SourceAddress const & sa, string const & msg);
|
||||
}
|
||||
|
||||
#define CHECK(x, msg) do { if (x) {} else { ::dbg::FireAssert(SRC(), ::msg::MessageList msg) } } while (false)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSERT(x, msg) CHECK(x, msg)
|
||||
#else
|
||||
#define ASSERT(x, msg)
|
||||
#endif
|
36
env/condition.hpp
vendored
Normal file
36
env/condition.hpp
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "mutex.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
class Condition : private noncopyable
|
||||
{
|
||||
public:
|
||||
Condition();
|
||||
~Condition();
|
||||
|
||||
void Lock() { m_mutex.Lock(); }
|
||||
void TryLock() { m_mutex.TryLock(); }
|
||||
void Unlock() { m_mutex.Unlock(); }
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
void Wait();
|
||||
|
||||
class Guard
|
||||
{
|
||||
Condition & m_cond;
|
||||
public:
|
||||
Guard(Condition & c) : m_cond(c) { m_cond.Lock(); }
|
||||
~Guard() { m_cond.Unlock(); }
|
||||
};
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
};
|
||||
|
||||
}
|
33
env/condition_posix.cpp
vendored
Normal file
33
env/condition_posix.cpp
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "condition.hpp"
|
||||
#include "posix.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
Condition::Condition()
|
||||
{
|
||||
CHECK_POSIX(::pthread_cond_init(&m_condition, 0));
|
||||
}
|
||||
|
||||
Condition::~Condition()
|
||||
{
|
||||
CHECK_POSIX(::pthread_cond_destroy(&m_condition));
|
||||
}
|
||||
|
||||
void Condition::Signal()
|
||||
{
|
||||
CHECK_POSIX(::pthread_cond_signal(&m_condition));
|
||||
}
|
||||
|
||||
void Condition::SignalAll()
|
||||
{
|
||||
CHECK_POSIX(::pthread_cond_broadcast(&m_condition));
|
||||
}
|
||||
|
||||
void Condition::Wait()
|
||||
{
|
||||
CHECK_POSIX(::pthread_cond_wait(&m_condition, &m_mutex.m_mutex));
|
||||
}
|
||||
|
||||
}
|
38
env/env.pro
vendored
Normal file
38
env/env.pro
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
TEMPLATE = app
|
||||
TARGET = env_tests
|
||||
CONFIG += console warn_on
|
||||
CONFIG -= app_bundle
|
||||
|
||||
INCLUDEPATH += ../3rdparty/boost ../3rdparty/googletest/include
|
||||
|
||||
HEADERS += \
|
||||
assert.hpp \
|
||||
condition.hpp \
|
||||
exception.hpp \
|
||||
file_handle.hpp \
|
||||
file_system.hpp \
|
||||
logging.hpp \
|
||||
message_list.hpp \
|
||||
mutex.hpp \
|
||||
posix.hpp \
|
||||
source_address.hpp \
|
||||
strings.hpp \
|
||||
writer.hpp \
|
||||
thread.hpp \
|
||||
|
||||
SOURCES += \
|
||||
assert.cpp \
|
||||
condition_posix.cpp \
|
||||
file_handle.cpp \
|
||||
file_system.cpp \
|
||||
logging.cpp \
|
||||
mutex_posix.cpp \
|
||||
posix.cpp \
|
||||
source_address.cpp \
|
||||
thread_posix.cpp \
|
||||
|
||||
# unit tests
|
||||
SOURCES += \
|
||||
../3rdparty/googletest/src/gtest-all.cc \
|
||||
../3rdparty/googletest/src/gtest_main.cc \
|
||||
tests/smoke.cpp \
|
18
env/exception.hpp
vendored
Normal file
18
env/exception.hpp
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "message_list.hpp"
|
||||
|
||||
namespace ex
|
||||
{
|
||||
|
||||
class Exception
|
||||
{
|
||||
string m_msg;
|
||||
public:
|
||||
Exception(string const & msg) : m_msg(msg) {}
|
||||
string const & Msg() const { return m_msg; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define THROWEX(klass, message) throw klass(::msg::MessageList message)
|
114
env/file_handle.cpp
vendored
Normal file
114
env/file_handle.cpp
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "file_handle.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "assert.hpp"
|
||||
#include "posix.hpp"
|
||||
|
||||
|
||||
namespace file
|
||||
{
|
||||
|
||||
FileHandle::FileHandle(string const & name, Mode mode)
|
||||
: m_name(name), m_mode(mode)
|
||||
{
|
||||
char const * const modes [] = {"rb", "wb", "r+b", "ab"};
|
||||
m_file = fopen(name.c_str(), modes[mode]);
|
||||
if (m_file)
|
||||
return;
|
||||
|
||||
if (mode == WRITE_EXISTING)
|
||||
{
|
||||
// if file doesn't exist "r+b" fails
|
||||
m_file = fopen(name.c_str(), "wb");
|
||||
if (m_file)
|
||||
return;
|
||||
}
|
||||
|
||||
THROWEX(FileException, (E2S()));
|
||||
}
|
||||
|
||||
FileHandle::~FileHandle()
|
||||
{
|
||||
if (m_file && fclose(m_file))
|
||||
LOG(WARNING, ("Error closing file", E2S()));
|
||||
}
|
||||
|
||||
string FileHandle::E2S() const
|
||||
{
|
||||
char const * s;
|
||||
switch (m_mode)
|
||||
{
|
||||
case READ: s = "Read"; break;
|
||||
case WRITE_TRUNCATE: s = "Write truncate"; break;
|
||||
case WRITE_EXISTING: s = "Write existing"; break;
|
||||
case APPEND: s = "Append"; break;
|
||||
}
|
||||
|
||||
return m_name + "; " + s + "; " + env::GetCError();
|
||||
}
|
||||
|
||||
static int64_t const INVALID_POS = -1;
|
||||
|
||||
uint64_t FileHandle::Size() const
|
||||
{
|
||||
int64_t const pos = ftell64(m_file);
|
||||
if (pos == INVALID_POS)
|
||||
THROWEX(FileException, (E2S(), pos));
|
||||
|
||||
if (fseek64(m_file, 0, SEEK_END))
|
||||
THROWEX(FileException, (E2S()));
|
||||
|
||||
int64_t const size = ftell64(m_file);
|
||||
if (size == INVALID_POS)
|
||||
THROWEX(FileException, (E2S(), size));
|
||||
|
||||
if (fseek64(m_file, pos, SEEK_SET))
|
||||
THROWEX(FileException, (E2S(), pos));
|
||||
|
||||
ASSERT(size >= 0, ());
|
||||
return static_cast<uint64_t>(size);
|
||||
}
|
||||
|
||||
void FileHandle::Read(void * p, size_t size)
|
||||
{
|
||||
size_t const readed = fread(p, 1, size, m_file);
|
||||
if (readed != size || ferror(m_file))
|
||||
THROWEX(FileException, (E2S(), readed, size));
|
||||
}
|
||||
|
||||
uint64_t FileHandle::Pos() const
|
||||
{
|
||||
int64_t const pos = ftell64(m_file);
|
||||
if (pos == INVALID_POS)
|
||||
THROWEX(FileException, (E2S()));
|
||||
|
||||
ASSERT(pos >= 0, ());
|
||||
return static_cast<uint64_t>(pos);
|
||||
}
|
||||
|
||||
void FileHandle::Seek(uint64_t pos)
|
||||
{
|
||||
if (fseek64(m_file, pos, SEEK_SET))
|
||||
THROWEX(FileException, (E2S(), pos));
|
||||
}
|
||||
|
||||
void FileHandle::Write(void const * p, size_t size)
|
||||
{
|
||||
size_t const written = fwrite(p, 1, size, m_file);
|
||||
if (written != size || ferror(m_file))
|
||||
THROWEX(FileException, (E2S(), written, size));
|
||||
}
|
||||
|
||||
void FileHandle::Flush()
|
||||
{
|
||||
if (fflush(m_file))
|
||||
THROWEX(FileException, (E2S()));
|
||||
}
|
||||
|
||||
void FileHandle::Truncate(uint64_t size)
|
||||
{
|
||||
int const res = ftruncate(fileno(m_file), size);
|
||||
if (res)
|
||||
THROWEX(FileException, (E2S(), size));
|
||||
}
|
||||
|
||||
}
|
54
env/file_handle.hpp
vendored
Normal file
54
env/file_handle.hpp
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include "exception.hpp"
|
||||
|
||||
#include "../std/cstdio.hpp"
|
||||
#include "../std/stdint.hpp"
|
||||
#include "../std/noncopyable.hpp"
|
||||
|
||||
|
||||
namespace file
|
||||
{
|
||||
|
||||
struct FileException : public ex::Exception
|
||||
{
|
||||
FileException(string const & msg) : ex::Exception(msg) {}
|
||||
};
|
||||
|
||||
inline string ToString(FileException const & ex)
|
||||
{
|
||||
return ex.Msg();
|
||||
}
|
||||
|
||||
class FileHandle : private noncopyable
|
||||
{
|
||||
public:
|
||||
/// Do not change order (@see cpp FileHandle::FileHandle)
|
||||
enum Mode { READ = 0, WRITE_TRUNCATE, WRITE_EXISTING, APPEND };
|
||||
|
||||
FileHandle(string const & fileName, Mode mode);
|
||||
~FileHandle();
|
||||
|
||||
uint64_t Size() const;
|
||||
uint64_t Pos() const;
|
||||
|
||||
void Seek(uint64_t pos);
|
||||
|
||||
void Read(void * p, size_t size);
|
||||
void Write(void const * p, size_t size);
|
||||
|
||||
void Flush();
|
||||
void Truncate(uint64_t sz);
|
||||
|
||||
string GetName() const { return m_name; }
|
||||
|
||||
private:
|
||||
FILE * m_file;
|
||||
string m_name;
|
||||
Mode m_mode;
|
||||
|
||||
/// Convert last error to string.
|
||||
string E2S() const;
|
||||
};
|
||||
|
||||
}
|
12
env/file_system.cpp
vendored
Normal file
12
env/file_system.cpp
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "file_system.hpp"
|
||||
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
bool DeleteFile(string const & path)
|
||||
{
|
||||
return (0 == remove(path.c_str()));
|
||||
}
|
||||
|
||||
}
|
11
env/file_system.hpp
vendored
Normal file
11
env/file_system.hpp
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "../std/string.hpp"
|
||||
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
bool DeleteFile(string const & path);
|
||||
|
||||
}
|
20
env/logging.cpp
vendored
Normal file
20
env/logging.cpp
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "logging.hpp"
|
||||
|
||||
#include "../std/iostream.hpp"
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
|
||||
string ToString(LogPriority pr)
|
||||
{
|
||||
static char const * arr[] = { "DEBUG", "INFO", "WARNING", "ERROR" };
|
||||
return arr[pr];
|
||||
}
|
||||
|
||||
void Print(LogPriority pr, SourceAddress const & sa, string const & msg)
|
||||
{
|
||||
cout << ToString(pr) << " " << sa.ToString() << msg << endl;
|
||||
}
|
||||
|
||||
}
|
17
env/logging.hpp
vendored
Normal file
17
env/logging.hpp
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "message_list.hpp"
|
||||
#include "source_address.hpp"
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
|
||||
enum LogPriority { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR };
|
||||
string ToString(LogPriority pr);
|
||||
|
||||
void Print(LogPriority pr, SourceAddress const & sa, string const & msg);
|
||||
|
||||
}
|
||||
|
||||
#define LOG(pr, message) ::dbg::Print(::dbg::LOG_##pr, SRC(), ::msg::MessageList message)
|
44
env/message_list.hpp
vendored
Normal file
44
env/message_list.hpp
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "strings.hpp"
|
||||
|
||||
|
||||
namespace msg
|
||||
{
|
||||
|
||||
inline string ToString(char const * s) { return s; }
|
||||
inline string ToString(string const & s) { return s; }
|
||||
|
||||
/// Override ToString function for your custom class in it's namespace.
|
||||
/// Your function will be called according to the ADL lookup.
|
||||
/// This is the default "last chance" implementation.
|
||||
template <class T>
|
||||
inline string ToString(T const & t)
|
||||
{
|
||||
return str::ToString(t);
|
||||
}
|
||||
|
||||
inline string MessageList()
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
inline string MessageList(T1 const & t1)
|
||||
{
|
||||
return ToString(t1);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline string MessageList(T1 const & t1, T2 const & t2)
|
||||
{
|
||||
return ToString(t1) + " " + ToString(t2);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
inline string MessageList(T1 const & t1, T2 const & t2, T3 const & t3)
|
||||
{
|
||||
return MessageList(t1, t2) + " " + ToString(t3);
|
||||
}
|
||||
|
||||
}
|
37
env/mutex.hpp
vendored
Normal file
37
env/mutex.hpp
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../std/noncopyable.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
class Condition;
|
||||
|
||||
class Mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
class Guard
|
||||
{
|
||||
Mutex & m_mutex;
|
||||
public:
|
||||
Guard(Mutex & m) : m_mutex(m) { m_mutex.Lock(); }
|
||||
~Guard() { m_mutex.Unlock(); }
|
||||
};
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
friend class Condition;
|
||||
};
|
||||
|
||||
}
|
33
env/mutex_posix.cpp
vendored
Normal file
33
env/mutex_posix.cpp
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "mutex.hpp"
|
||||
#include "posix.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
Mutex::Mutex()
|
||||
{
|
||||
CHECK_POSIX(::pthread_mutex_init(&m_mutex, 0));
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
CHECK_POSIX(::pthread_mutex_destroy(&m_mutex));
|
||||
}
|
||||
|
||||
void Mutex::Lock()
|
||||
{
|
||||
CHECK_POSIX(::pthread_mutex_lock(&m_mutex));
|
||||
}
|
||||
|
||||
bool Mutex::TryLock()
|
||||
{
|
||||
return (0 == ::pthread_mutex_trylock(&m_mutex));
|
||||
}
|
||||
|
||||
void Mutex::Unlock()
|
||||
{
|
||||
CHECK_POSIX(::pthread_mutex_unlock(&m_mutex));
|
||||
}
|
||||
|
||||
}
|
21
env/posix.cpp
vendored
Normal file
21
env/posix.cpp
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "posix.hpp"
|
||||
#include "logging.hpp"
|
||||
|
||||
#include "../std/cstring.hpp"
|
||||
|
||||
#include <cerrno> // for errno
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
void CheckPosixResult(int res)
|
||||
{
|
||||
if (res != 0)
|
||||
LOG(WARNING, (strerror(res)));
|
||||
}
|
||||
|
||||
char const * GetCError()
|
||||
{
|
||||
return strerror(errno);
|
||||
}
|
||||
}
|
10
env/posix.hpp
vendored
Normal file
10
env/posix.hpp
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
void CheckPosixResult(int res);
|
||||
char const * GetCError();
|
||||
}
|
||||
|
||||
#define CHECK_POSIX(x) env::CheckPosixResult(x)
|
16
env/source_address.cpp
vendored
Normal file
16
env/source_address.cpp
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "source_address.hpp"
|
||||
|
||||
#include "../std/sstream.hpp"
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
|
||||
string SourceAddress::ToString() const
|
||||
{
|
||||
ostringstream ss;
|
||||
ss << m_file << ", " << m_func << ", " << m_line << ": ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
31
env/source_address.hpp
vendored
Normal file
31
env/source_address.hpp
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "../std/string.hpp"
|
||||
|
||||
|
||||
namespace dbg
|
||||
{
|
||||
|
||||
class SourceAddress
|
||||
{
|
||||
char const * m_file;
|
||||
char const * m_func;
|
||||
int m_line;
|
||||
|
||||
public:
|
||||
SourceAddress(char const * file, char const * func, int line)
|
||||
: m_file(file), m_func(func), m_line(line)
|
||||
{
|
||||
}
|
||||
|
||||
string ToString() const;
|
||||
};
|
||||
|
||||
inline string ToString(SourceAddress const & sa)
|
||||
{
|
||||
return sa.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define SRC() ::dbg::SourceAddress(__FILE__, __FUNCTION__, __LINE__)
|
17
env/strings.hpp
vendored
Normal file
17
env/strings.hpp
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/sstream.hpp"
|
||||
|
||||
|
||||
namespace str
|
||||
{
|
||||
|
||||
template <class T> string ToString(T const & t)
|
||||
{
|
||||
ostringstream ss;
|
||||
ss << t;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
70
env/tests/smoke.cpp
vendored
Normal file
70
env/tests/smoke.cpp
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include "../file_handle.hpp"
|
||||
#include "../file_system.hpp"
|
||||
#include "../logging.hpp"
|
||||
|
||||
#include "../../std/algorithm.hpp"
|
||||
#include "../../std/vector.hpp"
|
||||
|
||||
|
||||
/// @note Do not edit formatting here (SRC() test):
|
||||
//@{
|
||||
namespace
|
||||
{
|
||||
string GetSourceAddress()
|
||||
{
|
||||
return SRC().ToString();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(EnvSmoke, SourceAddress)
|
||||
{
|
||||
string s = GetSourceAddress();
|
||||
size_t const beg = s.find_last_of('/');
|
||||
EXPECT_NE(beg, string::npos);
|
||||
s = s.substr(beg + 1);
|
||||
|
||||
size_t const end = s.find_last_of(',');
|
||||
EXPECT_NE(end, string::npos);
|
||||
string const test = s.substr(0, end);
|
||||
EXPECT_EQ(test, "smoke.cpp, GetSourceAddress");
|
||||
|
||||
ostringstream ss;
|
||||
ss << test << ", " << (__LINE__ - 17) << ": "; // magic constant
|
||||
EXPECT_EQ(s, ss.str());
|
||||
}
|
||||
//@}
|
||||
|
||||
|
||||
TEST(EnvSmoke, FileHandle)
|
||||
{
|
||||
typedef file::FileHandle HandleT;
|
||||
|
||||
char const * name = "file.bin";
|
||||
char const * buffer = "Some fellows believe in a dream until merry one!";
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
HandleT file(name, HandleT::WRITE_TRUNCATE);
|
||||
file.Write(buffer, strlen(buffer));
|
||||
}
|
||||
|
||||
{
|
||||
HandleT file(name, HandleT::READ);
|
||||
|
||||
size_t const n = strlen(buffer);
|
||||
vector<char> v(n);
|
||||
file.Read(v.data(), n);
|
||||
|
||||
EXPECT_TRUE(equal(v.begin(), v.end(), buffer));
|
||||
}
|
||||
}
|
||||
catch (file::FileException const & ex)
|
||||
{
|
||||
LOG(ERROR, (ex));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(fs::DeleteFile(name));
|
||||
}
|
37
env/thread.hpp
vendored
Normal file
37
env/thread.hpp
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../std/noncopyable.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
class Thread : private noncopyable
|
||||
{
|
||||
public:
|
||||
class Runnable : private noncopyable
|
||||
{
|
||||
bool m_cancelled;
|
||||
|
||||
public:
|
||||
Runnable() : m_cancelled(false) {}
|
||||
bool IsCancelled() const { return m_cancelled; }
|
||||
|
||||
virtual void Run() = 0;
|
||||
virtual void Cancel() { m_cancelled = true; }
|
||||
};
|
||||
|
||||
Thread() : m_runnable(0) {}
|
||||
|
||||
void Create(Runnable * runnable);
|
||||
void Join();
|
||||
void Cancel();
|
||||
|
||||
private:
|
||||
Runnable * m_runnable;
|
||||
pthread_t m_handle;
|
||||
};
|
||||
|
||||
}
|
37
env/thread_posix.cpp
vendored
Normal file
37
env/thread_posix.cpp
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "thread.hpp"
|
||||
#include "posix.hpp"
|
||||
|
||||
|
||||
namespace env
|
||||
{
|
||||
|
||||
void * PThreadProc(void * p)
|
||||
{
|
||||
Thread::Runnable * runnable = reinterpret_cast<Thread::Runnable *>(p);
|
||||
runnable->Run();
|
||||
|
||||
::pthread_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Thread::Create(Runnable * runnable)
|
||||
{
|
||||
m_runnable = runnable;
|
||||
CHECK_POSIX(::pthread_create(&m_handle, 0, &PThreadProc, reinterpret_cast<void *>(runnable)));
|
||||
}
|
||||
|
||||
void Thread::Join()
|
||||
{
|
||||
CHECK_POSIX(::pthread_join(m_handle, 0));
|
||||
}
|
||||
|
||||
void Thread::Cancel()
|
||||
{
|
||||
if (m_runnable)
|
||||
{
|
||||
m_runnable->Cancel();
|
||||
Join();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
39
env/writer.hpp
vendored
Normal file
39
env/writer.hpp
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "file_handle.hpp"
|
||||
|
||||
|
||||
namespace wr
|
||||
{
|
||||
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer() {}
|
||||
virtual void Write(void const * p, size_t size) = 0;
|
||||
};
|
||||
|
||||
class FileWriter : public Writer
|
||||
{
|
||||
typedef file::FileHandle HandleT;
|
||||
HandleT m_file;
|
||||
|
||||
public:
|
||||
FileWriter(string const & name)
|
||||
: m_file(name, HandleT::WRITE_TRUNCATE)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Write(void const * p, size_t size)
|
||||
{
|
||||
m_file.Write(p, size);
|
||||
}
|
||||
|
||||
uint64_t Size()
|
||||
{
|
||||
m_file.Flush();
|
||||
return m_file.Size();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
5
std/cstring.hpp
Normal file
5
std/cstring.hpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
// Used for memcpy, memcmp, strcpy, ...
|
||||
|
||||
#include <cstring>
|
6
tests.pro
Normal file
6
tests.pro
Normal file
|
@ -0,0 +1,6 @@
|
|||
cache()
|
||||
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS = env \
|
Reference in a new issue