Let's say I have a streaming API like this:
interface MyInterface {
addListener #0 (listener: Listener) -> (registration: RegisteredListener);
interface Listener {
update #0 () -> stream;
}
interface RegisteredListener {
}
}
I'm having a challenge where the destructor for the server implementation of MyInterface is running before the last registered interface has been released. How can I properly communicate the relationship to cap'n'proto RPC so that even if the client releases it's MyInterface::Client before the RegisteredListener::Client, that either MyInterface::Server lifetime is extended or the RegisteredListener::Server is smart enough to recognize that the original server instance its tracking the registration for is dead. Alternatively, am I misusing the API in some basic way?
Roughly the C++ code looks like this. Server:
class MyInterfaceImpl : public MyInterface {
class Registered final : public MyInterface::RegisteredListener::Server {
public:
Registered(MyInterfaceImpl* parent, uint64_t registrationId) : parent_(parent), id_(registrationId) {}
~Registered() {
parent->unregister(id_);
}
private:
MyInterfaceImpl *parent_;
uint64_t id_;
};
public:
kj::Promise<void> addListener(MyInterface::AddListenerContext context) {
auto registrationId = ++registrationId_;
clients_.emplace_back(context.getParams().getListener());
registrations_.emplace_back(registrationId);
context.getResult().setRegistration(kj::heap<Registered>(this, registrationId));
return kj::READY_NOW;
}
void unregister(uint64_t registrationId) {
auto found = std::find(registrations_.begin(), registrations_.end(), registrationId);
clients_.erase(clients_.begin() + (found - registrations_.begin()));
}
private:
std::vector<MyInterface::Listener::Client> clients_;
std::vector<uint64_t> registrations_;
uint64_t registrationId_ = 0;
};
The client code looks something like this:
capnp::EzRpcClient client("localhost:5923");
MyInterface::Client intf = client.getMain<MyInterface>();
auto& waitScope = client.getWaitScope();
auto listenerRequest = intf.addListenerRequest();
auto listenerPromise = listenerRequest.send();
listenerPromise.wait(waitScope);
{
auto listenerRequest2 = intf.addListenerRequest();
auto listenerPromise2 = listenerRequest2.send();
listenerPromise2.wait(waitScope);
}
Since this is all single-threaded it's pretty easy to spot the use-after-free. I put debug statements in ~MyInterfaceImpl and ~RegisteredListener and the second listener is getting unregistered after ~MyInterfaceImpl. I know that my add listener requests don't have the actual client object but I'm hoping that's not actually an important detail for this.
I recommend having Registered class hold a MyInterface::Client pointing to the parent, in addition to the plain pointer it currently holds.
MyInterfaceImpl *parent_;
MyInterface::Client ownParent_;
uint64_t id_;
This ensures that as long as a Registered still exists, the MyInterfaceImpl won't be destroyed.
Inside the implementation of addListener(), you can obtain a MyInterface::Client pointing to this by calling thisCap().
context.getResult().setRegistration(kj::heap<Registered>(
this, thisCap(), registrationId));
Related
I'm sorry if I don't know the right word for what I'm trying to accomplish.
Basically I have an event handler object which only has a single member. The member is a Stage object.
When the event handler receives an event, I want it to simply use the stage object to call the relevant method. For example:
Event event; //this event is not part of my code, but rather the library I'm using.
Stage s; // my custom class object
EventHandler event_handler; //also my custom class object
event_handler.stage = &s;
if(event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
So what I'm trying to accomplish is that, there will be seperate scopes that my program goes into over time, and I want each scope to have access to the event_handler such that they can do something like:
void some_other_scope(EventHandler* eh) {
Stage* some_new_stage = new Stage(...);
eh->stage = some_new_stage;
}
This way, the original event code stays the same, and the event handler will be calling handle_shutdown on a different object than it was originally going to.
So what I want to do is to overload the handle_shutdown method so that there can be different implementations of it. I know how basic overloading works, it can be done by specifying different parameters, but is there any way to have different definitions of the same class method based on the file that the object was created in?
I was hoping to have several files, each with their own some_other_scope() function, and each file can redefine the handle_shutdown method to do different things based on what that file needs.
I'm sure there's a way to do what I want, I just don't know the right words to use.
It seems you want to use polymorphism:
class IStage
{
public:
virtual ~IStage() = default;
virtual void handle_shutdown() = 0;
// ...
};
class Stage1 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
class Stage2 : public IStage
{
public:
void handle_shutdown() override { /*Implementation1*/ }
// ...
};
And then
struct EventHandler
{
std::unique_ptr<IStage> stage;
// ...
};
EventHandler event_handler;
event_handler.stage = std::make_unique<Stage1>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
// Later
event_handler.stage = std::make_unique<Stage2>();
if (event == SHUTDOWN) {
event_handler.stage->handle_shutdown();
}
I am trying to do a unit test to test the DoLogin method:
CLoginActivity::CLoginActivity()
{
m_pTask = new Task();
}
void CLoginActivity::DoLogin()
{
m_pTask.execute();
}
where the Task is another class that I need to mock.
class MockTask : public Task
{
public:
MOCK_METHOD0(Execute, void());
};
To inject the MockTask task object, I must change my construction:
CLoginActivity::CLoginActivity(Task& task)
{
m_pTask = task;
}
or write a set function:
CLoginActivity::SetTask(Task& task)
{
m_pTask = task;
}
Is there other method to inject instead those two methods? And I use gmock in my unit test project.
Injecting via constructor is the best - keep this design.
But there are few others ways for people that like to complicate simple things.
1) Make your CLoginActivity class template:
template <class TaskImpl>
class CLoginActivityTemplate
{
CLoginActivityTemplate() { m_pTask = new TaskImpl(); }
};
using CLoginActivity = CLoginActivityTemplate<Task>;
In your tests, test this instantion:
using CLoginActivityTestable = CLoginActivityTemplate<TaskMock>;
However it is not always so easy - because it is often hard to get access to this mock to set expentantions on it. But you might define TestMockWrapper class
to ensure access to mock task is easy:
class TestMockWrapper : public TestMock
{
public:
static TestMock* lastCreated;
TestMockWrapper() { lastCreated = this; }
};
using CLoginActivityTestable = CLoginActivityTemplate<TaskMockWrapper>;
2) Inject factory object to your constructor:
CLoginActivity::CLoginActivity(ITaskFactory& taskFactory)
{
m_pTask = taskFactory.create();
}
You need to mock this factory class to ensure mock-factory creates mock-object. Maybe it does not look promissing - but this is just intro to next point.
3) Have special factory function implemented in other file:
CLoginActivity.cpp
#include "TaskCreate.hpp"
CLoginActivity::CLoginActivity()
{
m_pTask = taskCreate();
}
TaskCreate.cpp
// your "real" function here
ITask* createTask() { return new Task(); }
Having such design- create UT test for your CLoginActivity with using only selected files from your projects - simple speaking - replace TaskCreate.cpp with TaskcreateStub.cpp in your UT project:
CloginActivity.cpp
TaskMock.cpp (if exists)
TaskCreateStub.cpp
TaskCreateStub.cpp should return task-mock - not real task. You need also access to this returned mock-object - so you can set expectations on it.
TaskCreateStub.cpp
// your "real" function here
static TaskMock* taskMockForCreateStub = nullptr;
ITask* createTask() { return taskMockForCreateStub ; }
void setTaskMockForCreateTaskStub(TaskMock* taskMock) { taskMockForCreateStub = taskMock; }
I strongly discourage you from using such linker-level mocking. Use it only for testing legacy code where you cannot redesign it and this might be the only way for using mock...
Current working on creating a Prism.DryIoc.Forms project to try out DryIoc (first time!).
In Xamarin.Forms there is a native DependencyService and to provide a nice way to migrate towards using Prism I would like to add it as a fallback container in case the requsted service type can't be resolved from the main container.
Current I have created a FallbackContainer and pass the instance of IContainerand overrides the methods for IResolver and delegates the rest of the IContainer calls to the instance passed during creation.
So after the default container is created and configured and then do
Container = CreateContainer();
ConfigureContainer();
Container.Rules.WithFallbackContainer(new DependencyServiceContainer(Container));
Is this the preferred method or is there any way just to attach a default IResolver?
Current implementation
public class FallbackDependencyServiceContainer : IContainer
{
private readonly IContainer container;
public FallbackDependencyServiceContainer(IContainer container)
{
this.container = container;
}
public object Resolve(Type serviceType, bool ifUnresolvedReturnDefault)
{
return ResolveFromDependencyService(serviceType);
}
public object Resolve(Type serviceType, object serviceKey, bool ifUnresolvedReturnDefault,
Type requiredServiceType,
RequestInfo preResolveParent, IScope scope)
{
return ResolveFromDependencyService(serviceType);
}
public IEnumerable<object> ResolveMany(Type serviceType, object serviceKey, Type requiredServiceType,
object compositeParentKey,
Type compositeParentRequiredType, RequestInfo preResolveParent, IScope scope)
{
return new[] { ResolveFromDependencyService(serviceType) };
}
private static object ResolveFromDependencyService(Type targetType)
{
if (!targetType.GetTypeInfo().IsInterface)
{
return null;
}
var method = typeof(DependencyService).GetTypeInfo().GetDeclaredMethod("Get");
var genericMethod = method.MakeGenericMethod(targetType);
return genericMethod.Invoke(null, new object[] { DependencyFetchTarget.GlobalInstance });
}
....
}
Thanks and looking forward to test DryIoc since I've read it's supposed to be the fastest out there
Updated answer:
You may directly use WithUnknownServiceResolvers returning DelegateFactory:
var c = new Container(Rules.Default.WithUnknownServiceResolvers(request =>
new DelegateFactory(_ => GetFromDependencyService(request.ServiceType))));
No need to implement IContainer just for that.
I think it may be optimized regarding performance by replacing DelegateFactory with ExpressionFactory. But I need some time to play with the idea.
I need to refactor class, which handles requests. I don't need chain of responsibility, because in compile time I have specified which request is connected to which handler.
My idea is to create one singleton class which is responsible for all logic.
For example it will have pointer to database object and it will handle requests.
There will be interface for HandlerMessage and many class derived from them.
Suppose we have:
class Singleton {
Database db;
int handleMessage(const Request& in, Response& out);
};
int Singleton::handleMessage(const Request& in, Response& out) {
int result = 0;
HandlerMessage* handler;
if(in.type == RequestType::A)
handler = new HandlerA();
else if(in.type == RequestType::B)
handler = new HandlerB();
else
return -1;
result = handler->handle(in, out);
delete handler;
return result;
}
However HandlerMessage needs to use Database and I wonder how to get use them.
I can pass pointer to database as an argument of handle function in HandlerMessage class.
However it seems to me strange, because all time I will pass the same argument. Moreover not all handlers needs to use database.
My question is:
class MessageHandler {
static Database* db;
}
this a good solutions, where I initialized db from MessageHandler class with db from SingeltonClass in Singleton constructor?
Or it is better to use more sophisticated solutions?
Thank You for any reply!
You can pass the reference to the database in the constructor of the handler like this:
handler = new HandlerA(db); //HandlerA needs to deal with database
handler = new HanlderB(); //HandlerB doesn't need to deal with database
HandlerA can look like this:
class HandlerA : public MessageHandler
{
HandlerA(Database& db) { /* ... */ }
int handle(const Request& in, Response& out) { /* ... */ }
};
I have a state machine with one state which dispatches some message (e.g. text) to an external receiver. Before transiting to this state (let's call it Dispatching) previous state needs somewhere to store that message so Dispatching can fetch it later. As message is created in one context and consumed in another, it will be created on the heap and State Manager object (which manages states, transitions and event loop) keeps a reference/pointer to it. State objects are created and destroyed as state machine transits through states. Each state inherits abstract base class State:
enum StateID
{
STATE_A,
STATE_B,
...
};
class State
{
public:
State(StateID stateID, StateManager& sm) :
stateID_(stateID), sm(sm_){}
virtual ~State(){};
virtual StateID HandleEvent(const Event& e) = 0;
StateID id() const {return stateID_;}
protected:
StateID stateID_;
StateManager& sm_;
};
In order to make passing data to the next state generic, I came up with the idea of StateData - a piece of information passed from one state to the next one. It is stored in dynamic memory, State Manager keeps a reference to it so each state can access it. As it is possible that different types of data will be passed to different states, StateData can be made abstract base class, specialized for each particular state:
struct StateData
{
virtual ~StateData() = 0;
};
struct StateAData : public StateData
{
int n_;
StateAData(int n) : n_(n){}
};
struct StateBData : public StateData
{
std::string str_;
StateBData(const std::string& str) : str_(str){}
};
...
class StateManager
{
boost::scoped_ptr<State> pCurrState_;
boost::scoped_ptr<StateData> pStateData_;
...
public:
void runEventLoop()
{
while(true)
{
...
//get event from a queue
...
StateID nextStateID = pCurrState_->HandleEvent(e);
if(nextStateID == pCurrState_->id())
continue;
pCurrState_.reset(0);
switch(nextStateID)
{
case STATE_A:
pCurrState_.reset(new StateA(*this));
break;
case STATE_B:
pCurrState_.reset(new StateB(*this));
break;
case STATE_C:
pCurrState_.reset(new StateC(*this));
break;
...
}
}
}
...
};
class StateA
{
public:
StateA(StateManager& sm) : State(STATE_A, sm){}
StateID HandleEvent(const Event& e)
{
switch(e.ID)
{
case EVENT_1:
{
StateAData* pData = reinterpret_cast<StateAData*>(stateMachine_.pStateData_.get());
// do something with data, e.g. use it for transition logic
if(pData->n_ % 2)
{
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
}
else
{
...
}
break;
}
...
}
}
...
}
There is a pitfall in following lines:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_B;
If transition logic changes so from here we need to go to STATE_C, developer can forget to change the type of StateBData to StateCData:
stateMachine_.pStateData_.reset(new StateBData("Hello from StateA"));
return STATE_C;
...which would lead to undesired behaviour when StateC tries to cast down StateData to StateCData.
How to avoid this? How to enforce matching the type of created object and returned enum value?
Yeah, this code stinks and this is the consequence of using two piece information and using enum to distinguish state types instead of types themselves. HandleEvent could return StateXData and depending on this returned type (as it carries the information about the next state) State Manager would determine (by using RTTI) the next state to transit to (X) but I don't like this solution.
Another idea is to create an instance of the next state and pass its data into its constructor but this approach would pollute state machine design as one state would be created before previous state is destroyed.
Make the enum part of the base class or provide a pure virtual function in the base class to return this enum. This way, the state itself will advertise its type.