Add a first draft of a message bus
This commit is contained in:
parent
712da0e988
commit
b3ca7926b2
|
@ -11,9 +11,11 @@
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include "common/logging.hpp"
|
#include "common/logging.hpp"
|
||||||
|
#include "common/messaging/bus.hpp"
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
static Logger logger;
|
static Logger logger;
|
||||||
|
static MessageBus messager(&logger);
|
||||||
|
|
||||||
// End globals
|
// End globals
|
||||||
|
|
||||||
|
@ -22,6 +24,10 @@ static void error_callback(int error, const char* description)
|
||||||
fprintf(stderr, "Error %d: %s\n", error, description);
|
fprintf(stderr, "Error %d: %s\n", error, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void debug_messagebus_callback(Message *m) {
|
||||||
|
logger.log(info, "(debug_messagebus_callback) Processed message: '%s'", m->name);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
@ -87,12 +93,19 @@ int main(int argc, char** argv)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
|
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
|
||||||
g_vertex_buffer_data, GL_STATIC_DRAW);
|
g_vertex_buffer_data, GL_STATIC_DRAW);
|
||||||
static Console console;
|
static Console console(&messager);
|
||||||
bool show_console = false;
|
bool show_console = false;
|
||||||
|
messager.registerCallback(&debug_messagebus_callback);
|
||||||
while(!glfwWindowShouldClose(window)) {
|
while(!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
// Process input.
|
// Process input.
|
||||||
|
|
||||||
|
// Process messages
|
||||||
|
int messages_treated = messager.processAll();
|
||||||
|
if (messages_treated > 0) {
|
||||||
|
logger.log(info, "Treated %d messages this tick", messages_treated);
|
||||||
|
}
|
||||||
|
|
||||||
// @TODO Game tick
|
// @TODO Game tick
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <ctype.h> // toupper
|
#include <ctype.h> // toupper
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common/messaging/bus.hpp"
|
||||||
|
|
||||||
struct Console
|
struct Console
|
||||||
{
|
{
|
||||||
char InputBuf[256];
|
char InputBuf[256];
|
||||||
|
@ -12,8 +14,9 @@ struct Console
|
||||||
ImGuiTextFilter Filter;
|
ImGuiTextFilter Filter;
|
||||||
bool AutoScroll;
|
bool AutoScroll;
|
||||||
bool ScrollToBottom;
|
bool ScrollToBottom;
|
||||||
|
MessageBus* messager;
|
||||||
|
|
||||||
Console()
|
Console(MessageBus *messager)
|
||||||
{
|
{
|
||||||
ClearLog();
|
ClearLog();
|
||||||
memset(InputBuf, 0, sizeof(InputBuf));
|
memset(InputBuf, 0, sizeof(InputBuf));
|
||||||
|
@ -26,6 +29,7 @@ struct Console
|
||||||
AutoScroll = true;
|
AutoScroll = true;
|
||||||
ScrollToBottom = false;
|
ScrollToBottom = false;
|
||||||
AddLog("Welcome to Dear ImGui!");
|
AddLog("Welcome to Dear ImGui!");
|
||||||
|
this->messager = messager;
|
||||||
}
|
}
|
||||||
~Console()
|
~Console()
|
||||||
{
|
{
|
||||||
|
@ -40,7 +44,7 @@ struct Console
|
||||||
static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)str, len); }
|
static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)str, len); }
|
||||||
static void Strtrim(char* str) { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
|
static void Strtrim(char* str) { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
|
||||||
|
|
||||||
void ClearLog()
|
void ClearLog()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Items.Size; i++)
|
for (int i = 0; i < Items.Size; i++)
|
||||||
free(Items[i]);
|
free(Items[i]);
|
||||||
|
@ -95,7 +99,7 @@ struct Console
|
||||||
AddLog("[debug] Parsed host '%s' [default:%d] and port '%s' [default:%d] from connect command.",
|
AddLog("[debug] Parsed host '%s' [default:%d] and port '%s' [default:%d] from connect command.",
|
||||||
host, !gotHost, port, !gotPort);
|
host, !gotHost, port, !gotPort);
|
||||||
// Raise an event
|
// Raise an event
|
||||||
|
this->messager->add("connect");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
|
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
#ifndef _MESSAGE_BUS_H
|
||||||
|
#define _MESSAGE_BUS_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common/logging.hpp"
|
||||||
|
|
||||||
|
struct MessageParam {
|
||||||
|
public:
|
||||||
|
int data_size;
|
||||||
|
void *data;
|
||||||
|
MessageParam(void *src, int size) {
|
||||||
|
data_size = size;
|
||||||
|
data = src;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message {
|
||||||
|
const char *name;
|
||||||
|
int parameter_count;
|
||||||
|
Message(const char *name) {
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MessageBus {
|
||||||
|
// arrray of things
|
||||||
|
// This class is responsible for allocating and freeing memory for the
|
||||||
|
// messages and their parameters.
|
||||||
|
private:
|
||||||
|
Message *bufferStart;
|
||||||
|
int bufferSize;
|
||||||
|
Message *occupiedHead;
|
||||||
|
Message *occupiedTail;
|
||||||
|
int count;
|
||||||
|
Logger *logger;
|
||||||
|
std::vector<void (*)(Message*)> callbacks;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MessageBus(Logger *l, int initial_size = 100) {
|
||||||
|
this->bufferSize = initial_size;
|
||||||
|
this->bufferStart = (Message *) calloc(initial_size, sizeof(struct Message));
|
||||||
|
this->occupiedHead = NULL; // the furthest "into" the buffer we are
|
||||||
|
this->occupiedTail = NULL; // the closest to the "start" of the buffer the useful bits are
|
||||||
|
this->count = 0;
|
||||||
|
this->logger = l;
|
||||||
|
l->log(info, "Initialized MessageBus with a buffer of %d items (%d bytes), starting at %d",
|
||||||
|
initial_size, initial_size*sizeof(struct Message), this->bufferStart);
|
||||||
|
}
|
||||||
|
~MessageBus() {
|
||||||
|
free(this->bufferStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerCallback(void (*fp)(Message*)) {
|
||||||
|
this->callbacks.push_back(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeCallback(void (*fp)(Message*)) {
|
||||||
|
bool found = false;
|
||||||
|
int i;
|
||||||
|
for(i = 0 ; i < this->callbacks.size(); i++) {
|
||||||
|
if (fp == this->callbacks.at(i)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
this->callbacks.erase(this->callbacks.begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const char *name) {
|
||||||
|
Message *new_item;
|
||||||
|
if (occupiedHead == NULL) {
|
||||||
|
new_item = this->bufferStart;
|
||||||
|
this->occupiedHead = this->bufferStart;
|
||||||
|
this->occupiedTail = this->bufferStart;
|
||||||
|
this->count++;
|
||||||
|
this->logger->log(info, "Added new item at start of empty buffer");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Do we have free space?
|
||||||
|
if (count < bufferSize) {
|
||||||
|
new_item = this->occupiedHead + sizeof(struct Message);
|
||||||
|
this->occupiedHead += sizeof(struct Message);
|
||||||
|
this->count++;
|
||||||
|
this->logger->log(info, "Added new item in buffer with free space");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Free up space (realloc, grow if necessary);
|
||||||
|
this->realloc();
|
||||||
|
new_item = this->occupiedHead + sizeof(struct Message);
|
||||||
|
this->occupiedHead += sizeof(struct Message);
|
||||||
|
this->count++;
|
||||||
|
this->logger->log(info, "Add new item after re-allocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_item->name = name;
|
||||||
|
this->logger->log(info, "%d items in MessageBus buffer", this->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove() {
|
||||||
|
this->occupiedTail += sizeof(struct Message);
|
||||||
|
this->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void realloc() {
|
||||||
|
// How much free space do we have at the start?
|
||||||
|
int start_available = (this->occupiedTail - this->bufferStart) / sizeof(struct Message);
|
||||||
|
// We'll do a full grow if there's less than 25% free
|
||||||
|
int newsize = this->bufferSize;
|
||||||
|
this->logger->log(info, "Re-allocating MessageBus buffer to gain some space");
|
||||||
|
if (start_available < this->bufferSize / 25) {
|
||||||
|
int newsize = this->bufferSize * 2;
|
||||||
|
this->logger->log(info, "Growing message buffer from %d to %d", this->bufferSize, newsize);
|
||||||
|
}
|
||||||
|
Message *newStart = (Message *) calloc(newsize, sizeof(struct Message));
|
||||||
|
int copySize = this->occupiedHead + sizeof(struct Message) - this->occupiedTail;
|
||||||
|
memcpy(newStart, this->occupiedTail, copySize);
|
||||||
|
Message *newHead;
|
||||||
|
newHead = newStart + (this->occupiedHead - this->occupiedTail);
|
||||||
|
this->bufferStart = newStart;
|
||||||
|
this->occupiedTail = newStart;
|
||||||
|
this->occupiedHead = newHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
int processAll() {
|
||||||
|
int done = 0;
|
||||||
|
while(this->count > 0) {
|
||||||
|
this->process();
|
||||||
|
done++;
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process() {
|
||||||
|
assert(this->count > 0);
|
||||||
|
// Call all the listening entities that care about this message or whatever
|
||||||
|
for (int i = 0 ; i < this->callbacks.size() ; i++) {
|
||||||
|
this->callbacks.at(i)(this->occupiedTail);
|
||||||
|
}
|
||||||
|
this->remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue