spacebox/src/Connection.hpp

156 lines
5.3 KiB
C++

/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
Connection objects contain a binary state of either on (connected) or off (not connected). When their state
is changed, an optional user supplied function corresponding to the state change is run automatically.
The functions each have the same return type, number of arguments, and argument types determined by the
template arguments.
By default, the state must change in order for a callback to be triggered. To allow repeat calls to
trigger a callback, the
Original test code:
Connection<> connection_d(std::bind(&Game::print_frame_length_history, this));
connection_d.toggle();
Connection<int, int, int> connection_f {
std::function<int(int, int)>(&glm::mod), std::function<int(int, int)>(&glm::mod) };
Connection<> connection_g = connection_d;
connection_g.toggle();
connection_g.disconnect();
int result;
result = connection_f.connect(3, 5);
std::cout << result << " ";
std::cout << connection_f.disconnect(20, 6) << " ";
result = connection_f.toggle(800, 120);
std::cout << result << std::endl;
result = connection_f.connect(111, 44);
std::cout << result << std::endl;
*/
#pragma once
#include <functional>
namespace sb
{
template<typename return_type = void, typename... arguments>
class Connection
{
private:
enum State : bool
{
STATE_OFF,
STATE_ON
};
using callback = std::function<return_type(arguments...)>;
State connection_state = STATE_OFF;
callback on_connect_callback, on_disconnect_callback;
public:
/*!
* Without any arguments, the connection object will be in the disconnected state with empty functions. Otherwise,
* the supplied functions will be added to the connection object. The first function argument will be run on a
* connection, and the second function argument will be run on a disconnection.
*
* @param on_connect_callback function to run on connection
* @param on_disconnect_callback function to run on disconnection
*/
Connection(callback on_connect_callback = callback(), callback on_disconnect_callback = callback())
{
if (on_connect_callback)
{
on_connect(on_connect_callback);
if (on_disconnect_callback)
{
on_disconnect(on_disconnect_callback);
}
}
}
/* Set the function that will run when a connection is made. */
void on_connect(callback on_connect)
{
on_connect_callback = on_connect;
}
/* Set the function that will run when a disconnection happens. */
void on_disconnect(callback on_disconnect)
{
on_disconnect_callback = on_disconnect;
}
/* Set state to Connection::STATE_ON and run response function. If return_type is non-void and the
* connection is already connected, the function will not run and the return value will be a default
* constructed value of the type return_type. Therefore, return_type must be default constructible. */
return_type connect(arguments... args)
{
if (!*this)
{
connection_state = STATE_ON;
if (on_connect_callback)
{
return on_connect_callback(args...);
}
}
return return_type();
}
/* Set state to Connection::STATE_OFF and run response function. If return_type is non-void and the
* connection is already disconnected, the function will not run and the return value will be a default
* constructed value of the type return_type. Therefore, return_type must be default constructible. */
return_type disconnect(arguments... args)
{
if (*this)
{
connection_state = STATE_OFF;
if (on_disconnect_callback)
{
return on_disconnect_callback(args...);
}
}
return return_type();
}
/* Set state to the opposite of current state, causing the appropriate response function to run. */
return_type toggle(arguments... args)
{
if (*this)
{
return disconnect(args...);
}
else
{
return connect(args...);
}
}
/* Return true if state is Connection::STATE_ON, false otherwise. */
bool connected()
{
return connection_state;
}
/* When called as a boolean, return the connection state. */
operator bool()
{
return connected();
}
};
}