-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e1a1108
commit dd9cdca
Showing
34 changed files
with
1,558 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef LINUX_LICENSE_H | ||
#define LINUX_LICENSE_H | ||
|
||
#include <string.h> | ||
|
||
static inline int license_is_gpl_compatible(const char *license) | ||
{ | ||
return (strcmp(license, "GPL") == 0 | ||
|| strcmp(license, "GPL v2") == 0 | ||
|| strcmp(license, "GPL and additional rights") == 0 | ||
|| strcmp(license, "Dual BSD/GPL") == 0 | ||
|| strcmp(license, "Dual MIT/GPL") == 0 | ||
|| strcmp(license, "Dual MPL/GPL") == 0); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
|
||
#include "object.hpp" | ||
#include "eventloop.hpp" | ||
|
||
namespace hope { | ||
namespace detail { | ||
class ObjectData; | ||
} | ||
|
||
namespace test { | ||
class ApplicationTestHelper; | ||
} | ||
|
||
class Application : public Object { | ||
public: | ||
Application(); | ||
~Application() override; | ||
|
||
void quit(int exit_code); | ||
|
||
void quit() { | ||
quit(0); | ||
} | ||
|
||
int exec(); | ||
|
||
private: | ||
friend class test::ApplicationTestHelper; | ||
|
||
EventLoop m_event_loop; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
|
||
#include <atomic> | ||
#include <utility> | ||
|
||
namespace hope { | ||
namespace detail { | ||
template<typename T> | ||
class AtomicWrapper { | ||
public: | ||
AtomicWrapper() = default; | ||
|
||
AtomicWrapper(T &&t) : m_atomic(std::move(t)) { | ||
|
||
} | ||
|
||
AtomicWrapper(const AtomicWrapper &other) : m_atomic(other.m_atomic.load()) { | ||
|
||
} | ||
|
||
AtomicWrapper(AtomicWrapper &&other) noexcept = delete; | ||
|
||
AtomicWrapper &operator=(const AtomicWrapper &other) { | ||
if (&other != this) { | ||
*this = AtomicWrapper(other); | ||
} | ||
|
||
return *this; | ||
} | ||
|
||
AtomicWrapper &operator=(AtomicWrapper &&other) noexcept = delete; | ||
|
||
const std::atomic<T> &value() const { | ||
return m_atomic; | ||
} | ||
|
||
std::atomic<T> &value() { | ||
return m_atomic; | ||
} | ||
|
||
private: | ||
std::atomic<T> m_atomic; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
|
||
namespace hope { | ||
class Connection { | ||
public: | ||
Connection(std::int64_t id) : m_valid(true), m_id(id) { | ||
|
||
} | ||
|
||
std::int64_t id() const { | ||
return m_id; | ||
} | ||
|
||
bool valid() const { | ||
return m_valid; | ||
} | ||
|
||
bool operator==(const Connection &other) const { | ||
return (m_id == other.m_id); | ||
} | ||
|
||
bool operator<(const Connection &other) const { | ||
return (m_id < other.m_id); | ||
} | ||
|
||
private: | ||
const bool m_valid = false; | ||
const std::int64_t m_id; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#pragma once | ||
|
||
namespace hope { | ||
class Event { | ||
public: | ||
virtual ~Event() = default; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
|
||
#include <map> | ||
#include <mutex> | ||
#include <vector> | ||
#include <memory> | ||
#include <thread> | ||
#include <algorithm> | ||
#include <condition_variable> | ||
|
||
#include "event.hpp" | ||
#include "object.hpp" | ||
#include "atomicwrapper.hpp" | ||
|
||
namespace hope { | ||
namespace detail { | ||
class ObjectData; | ||
} | ||
|
||
namespace test { | ||
class EventLoopTestHelper; | ||
} | ||
|
||
class EventLoop : public Object { | ||
public: | ||
using Mutex = std::mutex; | ||
using Locker = std::unique_lock<Mutex>; | ||
using Clock = std::chrono::steady_clock; | ||
using TimePoint = std::chrono::time_point<Clock>; | ||
|
||
EventLoop(); | ||
~EventLoop() override; | ||
|
||
bool is_running() const; | ||
|
||
void push_event(std::shared_ptr<Event> event, TimePoint when = Clock::now()); | ||
void push_event(std::shared_ptr<Event> event, std::chrono::milliseconds duration, TimePoint offset = Clock::now()); | ||
|
||
void quit(int exit_code = 0); | ||
int exec(); | ||
|
||
void register_object(Object *object); | ||
void unregister_object(Object *object); | ||
|
||
void on_event(Event *event) final; | ||
|
||
private: | ||
friend class EventLoopTestHelper; | ||
|
||
int loop(); | ||
|
||
void process_events(const std::vector<std::shared_ptr<Event>> &events); | ||
void cleanup_objects(); | ||
|
||
int m_exit_code = 0; | ||
bool m_exit = false; | ||
bool m_is_running = false; | ||
mutable Mutex m_mutex; | ||
mutable Mutex m_objects_mutex; | ||
std::condition_variable m_cond; | ||
std::multimap<TimePoint, std::shared_ptr<Event>> m_events; | ||
std::map<Object *, hope::detail::AtomicWrapper<bool>> m_objects; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
#include "timer.hpp" | ||
#include "event.hpp" | ||
#include "thread.hpp" | ||
#include "signal.hpp" | ||
#include "optional.hpp" | ||
#include "eventloop.hpp" | ||
#include "threaddata.hpp" | ||
#include "objectdata.hpp" | ||
#include "connection.hpp" | ||
#include "application.hpp" | ||
#include "atomicwrapper.hpp" | ||
#include "indexsequence.hpp" | ||
#include "objectinvoker.hpp" | ||
#include "queuedinvokationevent.hpp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#pragma once | ||
|
||
#include <cstddef> | ||
|
||
namespace hope { | ||
namespace detail { | ||
template <std::size_t ... T> | ||
struct index_sequence { | ||
|
||
}; | ||
|
||
template<std::size_t K, std::size_t ...Remainder> | ||
struct index_sequence_builder { | ||
using result = typename index_sequence_builder < K - 1, K - 1, Remainder... >::result; | ||
}; | ||
|
||
template<std::size_t ...Remainder> | ||
struct index_sequence_builder<0, Remainder...> { | ||
using result = index_sequence<Remainder...>; | ||
}; | ||
|
||
template<std::size_t T> | ||
using make_index_sequence = typename index_sequence_builder<T>::result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#pragma once | ||
|
||
#include <atomic> | ||
#include <thread> | ||
#include <iostream> | ||
|
||
namespace hope { | ||
class Event; | ||
class Thread; | ||
|
||
namespace detail { | ||
class ObjectData; | ||
} | ||
|
||
class Object { | ||
public: | ||
Object(); | ||
virtual ~Object(); | ||
|
||
void move_to_thread(Thread *thread); | ||
void move_to_thread(std::thread::id thread); | ||
|
||
virtual void on_event(Event *event); | ||
|
||
protected: | ||
Object(bool initialize); | ||
|
||
void terminate(); | ||
void initialize(); | ||
|
||
std::atomic<bool> m_initialized; | ||
std::atomic<bool> m_terminated; | ||
std::shared_ptr<hope::detail::ObjectData> m_data; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#pragma once | ||
|
||
#include <map> | ||
#include <mutex> | ||
#include <memory> | ||
#include <thread> | ||
|
||
namespace hope { | ||
class Object; | ||
|
||
namespace detail { | ||
class ObjectData { | ||
public: | ||
ObjectData(std::thread::id id) : m_thread_id(std::move(id)) { | ||
|
||
} | ||
|
||
std::unique_lock<std::mutex> lock() { | ||
return lock(*this); | ||
} | ||
|
||
static std::unique_lock<std::mutex> lock(const std::shared_ptr<ObjectData> &data) { | ||
return data ? lock(*data) : std::unique_lock<std::mutex>(); | ||
} | ||
|
||
static std::unique_lock<std::mutex> lock(ObjectData &data) { | ||
return std::unique_lock<std::mutex>(data.m_mutex); | ||
} | ||
|
||
static std::pair<std::unique_lock<std::mutex>, std::unique_lock<std::mutex>> lock(const std::shared_ptr<ObjectData> &first, const std::shared_ptr<ObjectData> &second) { | ||
if (first && second) { | ||
return lock(*first, *second); | ||
} else if (first) { | ||
return { lock(*first), std::unique_lock<std::mutex>() }; | ||
} else if (second) { | ||
return { lock(*second), std::unique_lock<std::mutex>() }; | ||
} else { | ||
return { std::unique_lock<std::mutex>(), std::unique_lock<std::mutex>() }; | ||
} | ||
} | ||
|
||
static std::pair<std::unique_lock<std::mutex>, std::unique_lock<std::mutex>> lock(ObjectData &first, ObjectData &second) { | ||
ObjectData *first_address = &first; | ||
ObjectData *second_address = &second; | ||
|
||
if (first_address >= second_address) { | ||
std::swap(first_address, second_address); | ||
} | ||
|
||
std::unique_lock<std::mutex> first_lock = lock(*first_address); | ||
std::unique_lock<std::mutex> second_lock; | ||
if (first_address != second_address) { | ||
second_lock = lock(*second_address); | ||
} | ||
|
||
return {std::move(first_lock), std::move(second_lock)}; | ||
} | ||
|
||
std::thread::id m_thread_id; | ||
std::mutex m_mutex; | ||
}; | ||
|
||
class ObjectDataRegistry { | ||
public: | ||
static ObjectDataRegistry &instance(); | ||
|
||
ObjectDataRegistry(const ObjectDataRegistry &) = delete; | ||
ObjectDataRegistry(ObjectDataRegistry &&) = delete; | ||
|
||
ObjectDataRegistry &operator=(const ObjectDataRegistry &) = delete; | ||
ObjectDataRegistry &operator=(ObjectDataRegistry &&) = delete; | ||
|
||
std::weak_ptr<ObjectData> data(Object *object) { | ||
auto it = m_data.find(object); | ||
return it != m_data.end() ? it->second : std::weak_ptr<ObjectData>(); | ||
} | ||
|
||
void register_object_data(Object *object, const std::shared_ptr<ObjectData> &data) { | ||
m_data.emplace(object, data); | ||
} | ||
|
||
void unregister_object_data(Object *object) { | ||
m_data.erase(object); | ||
} | ||
|
||
private: | ||
ObjectDataRegistry() = default; | ||
|
||
std::map<Object *, std::weak_ptr<ObjectData>> m_data; | ||
}; | ||
} | ||
} |
Oops, something went wrong.