Skip to content

Commit

Permalink
add hope
Browse files Browse the repository at this point in the history
  • Loading branch information
jiale-gdyd committed Nov 2, 2022
1 parent e1a1108 commit dd9cdca
Show file tree
Hide file tree
Showing 34 changed files with 1,558 additions and 0 deletions.
1 change: 1 addition & 0 deletions configs/host_unittest_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ CONFIG_HOST_LIBDRM_DISP=y

# CONFIG_HOST_UNITTEST_SIGSLOT is not set
# CONFIG_HOST_SIGNAL_SLOTS is not set
# CONFIG_HOST_SIGSLOT_THREADED_PRODUCER_CONSUMER is not set

#
# hardware platform
Expand Down
16 changes: 16 additions & 0 deletions include/linux/license.h
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
33 changes: 33 additions & 0 deletions project/3rdparty/include/hope/application.hpp
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;
};
}
45 changes: 45 additions & 0 deletions project/3rdparty/include/hope/atomicwrapper.hpp
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;
};
}
}
32 changes: 32 additions & 0 deletions project/3rdparty/include/hope/connection.hpp
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;
};
}
8 changes: 8 additions & 0 deletions project/3rdparty/include/hope/event.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

namespace hope {
class Event {
public:
virtual ~Event() = default;
};
}
64 changes: 64 additions & 0 deletions project/3rdparty/include/hope/eventloop.hpp
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;
};
}
16 changes: 16 additions & 0 deletions project/3rdparty/include/hope/hope.hpp
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"
25 changes: 25 additions & 0 deletions project/3rdparty/include/hope/indexsequence.hpp
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;
}
}
35 changes: 35 additions & 0 deletions project/3rdparty/include/hope/object.hpp
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;
};
}
92 changes: 92 additions & 0 deletions project/3rdparty/include/hope/objectdata.hpp
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;
};
}
}
Loading

0 comments on commit dd9cdca

Please sign in to comment.