skui学习笔记(二)模块分析

四、模块分析

skui分为几个模块:

# skui itself
add_subdirectory(core)
add_subdirectory(css)
add_subdirectory(graphics)
add_subdirectory(gui)
add_subdirectory(opengl)
add_subdirectory(system)

目前example里面例程用到的只有core、graphics、gui三个模块。

1、core

基本功能,包括信号,属性,字符串,路径,应用程序,操作系统抽象

c++和h++后缀的文件作者是为了防止和其它文件重名,这几种后缀名没有区别,如果编译器支持的话,哪种后缀都是一样的,在C++ Primer上给出如下说明:

Unix uses: C, cc, cxx, c
GNU C++ uses: C, cc, cxx, cpp, c++
Digital Mars uses: cpp, cxx
Borland C++ uses: cpp
Watcom uses: cpp
Microsoft Visual C++ uses: cpp, cxx, cc
Metrowerks CodeWarrior uses: cpp, cp, cc, cxx, c++

application类

在application构造函数中创建application实例

 application::application(int argc, char* argv[], string name)
    : commandline_arguments{argv+1, argv+argc}
    , name{std::move(name)}
  {
    if(implementation::instance != nullptr)
    {
      std::cerr << "skui::core::application: creating a second application instance is not allowed.\n";
      implementation::instance->quit();
    }
    implementation::instance = this;
  }

提供方法获取实例

application& application::instance()
  {
    if(implementation::instance == nullptr)
    {
      std::cerr << "skui::core::application::instance: application instance not created.\n";
      std::exit(EXIT_FAILURE);
    }
    return *implementation::instance;
  }

呵,浓浓的C语言风格代码布局。

在application类中定义core::event_loop的实例event_loop

appcation的事件执行和退出

  int application::execute()
  {
    return event_loop.execute();
  }

  void application::quit(int exit_code)
  {
    about_to_quit.emit();
    event_loop.stop(exit_code);
  }

event_loop类

用来处理事件循环
里面一共有这几个方法:execute、push、stop、interrupt

execute

int event_loop::execute()
  {
    while(!exit)
    {
      // wait on the queue to receive work
      queue.wait();

      auto commands = queue.take_commands();

      if(filter)
        filter(commands);

      while(!commands.empty() && !exit)
      {
        commands.front()->execute();
        commands.pop_front();
      }
    }
    return exit_code;
  }

push

void event_loop::push(command_queue::command_ptr&& command)
  {
    queue.push(std::move(command));
  }

stop

void event_loop::stop(int return_code)
  {
    exit_code = return_code;
    queue.push(std::make_unique<command>([this] { exit = true; }));
  }

interrupt

void event_loop::interrupt(int return_code)
  {
    exit_code = return_code;
    queue.push_front(std::make_unique<command>([this] { exit = true; }));
  }

都是在对command_queue类操作

command类

在看command_queue类之前先看command类
里面定义了一个模板和属性std::function<void()> function

template<typename Callable, typename... ArgTypes>
    command(Callable callable, ArgTypes... args)
      : function{[callable, args...] { return callable(args...); }}
    {}
std::function<void()> function;

创建一个 std::function 类的对象去捕获 lambda 函数(有问题的可以看下匿名函数)

构造函数中把Callable传给function

command::command()
    : function{[] {}}
  {}

方法execute中执行function

void command::execute()
  {
    function();
  }
command_queue类

用using实现别名,定义了一个双端队列commands_type,里面保存的是command类型的智能指针,用来储存渲染命令

using command_ptr = std::unique_ptr<command>;
using commands_type = std::deque<command_ptr>;

push:尾插新元素到deque

void command_queue::push(command_ptr&& command)
  {
    const std::lock_guard lock{queue_mutex};

    queue.push_back(std::move(command));
    condition_variable.notify_one();
  }

呵,不得不吐槽一下这个csdn编辑器代码块不能取消格式,只能去清浏览器缓存
push_front:头插新元素到deque

void command_queue::push_front(command_queue::command_ptr&& command)
  {
    std::lock_guard lock{queue_mutex};

    queue.push_front(std::move(command));
    condition_variable.notify_one();
  }

wait:通过条件变量和互斥锁等待

void command_queue::wait()
  {
    std::unique_lock lock{queue_mutex};

    if(queue.empty())
      condition_variable.wait(lock, [this] { return !queue.empty(); });
  }

take_commands:获取queue并清空command_queue的属性queue

command_queue::commands_type command_queue::take_commands()
  {
    const std::lock_guard lock{queue_mutex};

    commands_type result;
    std::swap(result, queue);

    return result;
  }
debug.h++

定义了log打印,加上了时间

inline void debug_print(ArgTypes... args)
{
	auto& stream = std::cerr;
    core::ostream_format_keeper guard(stream);
    const auto now = std::chrono::system_clock::now();
    const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
    const auto time = std::chrono::system_clock::to_time_t(now);
    const auto utc_time = std::gmtime(&time);

    stream << std::put_time(utc_time, "%FT%T.")
           << std::setprecision(4) << std::setfill('0') << std::setw(3) << ms.count()
           << std::put_time(utc_time, "%z: ");
    stream << std::boolalpha;
    stream << std::setprecision(15);
    ((stream << args), ...);
}
library类

使用dlopen加载动态库

load

bool library::load(path filename_to_load)
  {
    if(filename == filename_to_load)
    {
      if(native_handle)
        return true;
    }
    else
    {
      if(!filename_to_load.empty())
        filename = std::move(filename_to_load);
    }
    native_handle = implementation::load(filename.c_str());

    return native_handle != nullptr;
  }

unload

bool library::unload()
  {
    bool result = true;
    if(native_handle != nullptr)
      result = implementation::unload(native_handle);

    native_handle = nullptr;

    return result;
  }

下面是有关C++实现信号(signal)和槽(slot)的部分

(╯°Д°)╯︵ ┻━┻

trackable类

定义了一个基类tracker,定义了trackable的删除、拷贝、移动。

class tracker
    {
    public:
      virtual void trackable_deleted(const trackable* object) = 0;
      virtual void trackable_copied(const trackable* old_object, const trackable* new_object) = 0;
      virtual void trackable_moved(const trackable* old_object, const trackable* new_object) = 0;

    protected:
      tracker() = default;
      virtual ~tracker() = default;
    };

下面是主角trackable

class trackable
  {
  public:
    virtual ~trackable();

    trackable(const trackable& other);
    trackable(trackable&& other) noexcept;
    trackable& operator=(trackable other);

    void track(implementation::tracker* tracker) const;
    void untrack(implementation::tracker* tracker) const;

  protected:
    trackable() = default;

  private:
    // mutable so you can be track const objects
    mutable std::unordered_set<implementation::tracker*> trackers;
    mutable std::mutex trackers_mutex;
  };

unordered_set本质是使用hash散列的方式存储数据,是一种使用hash值作为key的容器.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值