Reference data members and move constructor - c++

Assuming the following code:
class ChannelHandle;
class SessionHandle;
typedef ChannelHandle& ChannelHandleRef;
typedef SessionHandle& SessionHandleRef;
class RemoteChannelHandle
{
public:
RemoteChannelHandle(
ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle);
RemoteChannelHandle(RemoteChannelHandle&&);
~RemoteChannelHandle();
void CloseChannel();
#ifndef _MSC_VER
RemoteChannelHandle& operator=(RemoteChannelHandle&&) = delete;
RemoteChannelHandle(RemoteChannelHandle const&) = delete;
RemoteChannelHandle& operator=(RemoteChannelHandle const&) = delete;
#endif
private:
LIBSSH2_CHANNEL* channel;
ChannelHandleRef channelHandle;
SessionHandleRef sessionHandle;
};
RemoteChannelHandle::RemoteChannelHandle(
ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle)
: channel(nullptr), channelHandle(pChannelHandle), sessionHandle(pSessionHandle)
{
// OPEN SSH CHANNEL
}
RemoteChannelHandle::~RemoteChannelHandle()
{
try
{
CloseChannel();
}
catch (...)
{ }
}
void RemoteChannelHandle::CloseChannel()
{
if (channel == nullptr)
{
return;
}
// CLOSE SSH CHANNEL. THROW IF SOMETHING GOES WRONG
channel = nullptr;
}
RemoteChannelHandle opens an SSH channel, but the cleanup requires
two steps (close + free). The first step is performed in
~RemoteChannelHandle(), but the second will be performed in
ChannelHandle's dtor; hence the data member channelHandle, since
we'll need to inject channel into it. This reference could be
eliminated by performing both steps in ~RemoteChannelHandle().
sessionHandle holds the LIBSSH2_SESSION* necessary to open the SSH
channel. Since I don't want to pass LIBSSH2_SESSION* around, this
reference can't be eliminated.
The problem happens when I define a move ctor for RemoteChannelHandle. I need to clear the members of the "moved from" instance. However, there's no way to clear the reference. So, what to do here?
Use (const) std::shared_ptr instead of references? I could even use
naked pointers, as there's no ownership involved. I realize there's some debate
regarding the use of references as data members, but apart from the
move ctor, I foresee no other scenario where I would need to reseat
the handles (which is why I used references in the first place).
Leave the references as they are, and create a "state" data member
specifically to check if the object is in a valid state (I can use channel != nullptr
for this purpose)?
Any other idea?
I've searched for alternatives to this, and found no clear answer. Which could mean there's actually no clear answer, of course.
Thanks for your time.
Edit (in reply to Mankarse):
ChannelHandle exists solely to perform step 2 of cleanup. Here's a simplified definition:
class ChannelHandle
{
public:
ChannelHandle();
ChannelHandle(ChannelHandle&&);
~ChannelHandle();
#ifndef _MSC_VER
ChannelHandle& operator=(ChannelHandle&&) = delete;
ChannelHandle(ChannelHandle const&) = delete;
ChannelHandle& operator=(ChannelHandle const&) = delete;
#endif
LIBSSH2_CHANNEL* GetChannel() { return channel; }
void SetChannel(LIBSSH2_CHANNEL* pChannel) { channel = pChannel; }
void FreeChannel();
private:
LIBSSH2_CHANNEL* channel;
};
SessionHandle is an RAII encapsulation for a LIBSSH2_SESSION*. It calls libssh2_session_init() on ctor and libssh2_session_free() on dtor. Other similar classes take care of other steps of the SSH session's init/cleanup, but this is where we get the LIBSSH2_SESSION* from libssh2, and SessionHandle owns it. Once again, a simplified definition:
class SessionHandle
{
public:
SessionHandle();
SessionHandle(SessionHandle&&);
~SessionHandle();
void CloseSession();
LIBSSH2_SESSION* GetSession() { return session; }
#ifndef _MSC_VER
SessionHandle& operator=(SessionHandle&&) = delete;
SessionHandle(SessionHandle const&) = delete;
SessionHandle& operator=(SessionHandle const&) = delete;
#endif
private:
LIBSSH2_SESSION *session;
};

You've answered the question yourself:
I could even use naked pointers, as there's no ownership involved.

Related

How can I elegantly synchronize access to an arbitrary buffer?

I have a buffer that is currently accessed via a pointer to the beginning of the buffer. I'm trying to come up with a way to guarantee nobody can access the buffer unless they hold a lock on it. For example:
class Buffer {
friend class BufferGuard;
std::mutex mutex;
void* buffer;
}
struct BufferGuard {
BufferGuard(Buffer& parent) { parent.mutex.lock() }
~BufferGuard() { parent.mutex.unlock(); }
void* Get() { return parent.buffer; }
}
However this is easily defeated by saving the result of BufferGuard::Get. This solution, as well as any others I can think of, rely on users of my library being well behaved. Am looking for a solution where misbehaving isn't an option.
You cannot guarantee that people cannot break your guard while giving them access to a trivially copyable object like void*. However, you can make it more explicitly obvious that the user is doing something wrong:
struct BufferGuard {
private:
Buffer& parent;
public:
BufferGuard(Buffer& parent) : parent{parent} { parent.mutex.lock() }
~BufferGuard() { parent.mutex.unlock(); }
BufferGuard(BufferGuard const&) = delete;
BufferGuard(BufferGuard&&) = delete;
BufferGuard& operator=(BufferGuard const&) = delete;
BufferGuard& operator=(BufferGuard&&) = delete;
template <std::regular_invocable<void*> Op>
void operate(Op&& operation) {
std::forward<Op>(operation)(parent.buffer);
}
}
void usecase(Buffer& buffer) {
BufferGuard guard{buffer};
guard.operate([](void* buf) { new(buf) int{7}; })
}
This means, you don't directly return the pointer to use freely; Your user can only do something with the pointer as long as your guard is around. And as long as your guard is around, your lock is alive. Of course, a nifty user will find a way to hoist the pointer value out of the callback, but it takes intent to misuse the interface.

Non-Copyable Within Class

I've been working on a server written in C++ and using SFML networking for the sockets and all. However, I've ran into a bit of a dead end for me. SFML Sockets are non-copyable and thus cannot be stored into most(all the ones that I know of) stl containers.
So, I quickly jumped to the idea of using a pointer and then it hit me that I should use RAII, but I hate smart pointers and needed to store more information than just the pointer to the Socket class.
I wrote a Client class that wraps the socket and deletes it when the destructor on the Client class gets called, which is fine and dandy..until I remembered that the stl containers will copy my class, delete the pointer and then I'd be left with a dangling pointer.
So, is there anyway I can get around non-copyables? I need the pointer to be stored within the class and I need the class to destroy the allocated memory.
I figured I could use a copy constructor to set the copied classes' pointer to null, but I cannot find a way to do that.
For Reference:
Client.cpp
Client::Client()
{
};
Client::Client(sf::TcpSocket* in_Connection)
{
m_Connection = in_Connection;
m_IPAddress = m_Connection->getRemoteAddress().toString();
m_AccountName = "NOACCOUNT";
m_CharacterName = "NOCHARACTER";
};
Client::~Client()
{
m_Connection->disconnect();
delete m_Connection;
};
//getters
sf::TcpSocket* Client::getConnection()
{
return m_Connection;
};
std::string Client::getIPAddress()
{
return m_IPAddress;
};
std::string Client::getAccountName()
{
return m_AccountName;
};
std::string Client::getCharacterName()
{
return m_CharacterName;
};
//setters -- Account Name and Character Name are the only two that can be changed during a connection.
void Client::setAccountName(std::string in_AccountName)
{
m_AccountName = in_AccountName;
};
void Client::setCharacterName(std::string in_CharacterName)
{
m_CharacterName = in_CharacterName;
};
//Copy Constructor <--This defintely won't work and I know that, haha.
Client::Client(const Client& that)
{
m_Connection = new sf::TcpSocket();
*m_Connection = *that.m_Connection; // Cannot copy non-copyable
m_IPAddress = that.m_IPAddress;
m_CharacterName = that.m_CharacterName;
m_AccountName = that.m_AccountName;
};
Server Accept Function
void Server::AcceptConnections()
{
sf::TcpSocket* Socket = new sf::TcpSocket();
if( m_Listener.accept(*Socket) == sf::Socket::Done)
{
if(Socket != NULL )
{
std::string IPAddress = Socket->getRemoteAddress().toString();
if( m_Connections.find( IPAddress ) == m_Connections.end() )
{
std::cout << IPAddress;
std::cout << " Has Connected.";
std::endl( std::cout );
m_Connections.insert( std::make_pair(IPAddress, Client(Socket) ) );
}
}
}
};
First of all, whether you can use C++11 or not is a game changer.
In C++11, you have the concept of move. Unlike copying, moving is not about duplicating but about transferring. All Standard containers were adapted to non-copyable classes that are movable.
An example of a movable class:
class Client {
public:
Client(Client const&) = delete; // non copyable
Client& operator=(Client const&) = delete; // non copy assignable
Client(Client&&) = default; // movable
Client& operator=(Client&&) = default; // move assignable
private:
std::unique_ptr<sf::TcpSocket> _socket;
};
And your problem is solved.
If you are stuck in C++03 land, you are in for a bit of trouble. The simplest solution would be to use a manager class:
the manager owns the instance
users of the instance only ever manipulates references/pointers to it

Storing multiple Lua states in a Boost shared_ptr

I haven't used boost before, so forgive me if I am doing something silly. I have a class which holds a lua_State. I have a boost::shared_ptr vector which I push_back new states like so:
class Lua_State
{
lua_State *L;
std::string m_scr;
public:
Lua_State() : L(luaL_newstate())
{
lua_register(L, "test", test);
luaL_openlibs(L);
}
~Lua_State() {
lua_close(L);
}
inline bool LoadScript(const char* script)
{
if (!boost::filesystem::exists(script))
return false;
m_scr = fs::path(std::string(script)).filename().string();
chdir(fs::path(scr).parent_path().string().c_str());
if (luaL_loadfile(L, m_scr.c_str()))
return false;
// prime
if (lua_pcall(L, 0, 0, 0))
return false;
return true;
}
};
typedef boost::shared_ptr<Lua_State> LUASTATEPTR;
class Scripts
{
private:
std::vector<LUASTATEPTR> m_Scripts;
public:
Scripts() { }
void TestLoad()
{
m_Scripts.push_back(LUASTATEPTR(new Lua_State()));
LUASTATEPTR pState = m_Scripts[0];
pState->LoadScript("C:/test.lua");
}
};
The code works and the Lua state is added, but after a few seconds the application crashes. I am at a loss as to why this is happening. It works fine when I do it manually (without shared_ptrs and manually dereferencing).
You have violated the rule of 31. You created a non-trivial destructor and allocating constructor without disabling or writing a copy constructor and operator=.
Probably when you create the shared_ptr you are doing a copy of the above class. The temporary is then discarded and things go boom.
So, first disable LuaState::operator=(LuaState const&) and LuaState(LuaState const&) constructor (make a private non-implemented version, or in C++11 delete it), or implement it.
Next, use make_shared<LuaState>() to create your shared_ptr<LuaState> instances. This will create them "in place" and remove the copy.
1 What is this Rule of 3 I speak of? See these links: Rule of Three (Wikipedia), What is the Rule of Three?

Accessing variable outside scope of a callback c++

I have been beating my head around this issue of static versus non-static, callback functions, function pointers, etc... My goal is to access data of a struct outside the scope of my callback interface. I am trying to do this within my class called TextDetect. I thought I was on track when I asked this question: Avoiding a static member function in c++ when using a callback interface from C
However, I still can't access the data without losing scope over the data that I am most interested. At runtime, I get "Access violation reading location ..." I'll point it out below where it fails.
I implemented the answer to my previous question as the following class, shown entirely (Note: vtrInitialize is part of a 3rd party api code int vtrInitialize(const char *inifile, vtrCallback cb, void *calldata);):
class TextDetect {
const char * inifile;
vtrImage *vtrimage;
int framecount;
public:
TextDetect();
~TextDetect();
void vtrCB(vtrTextTrack *track);
static void vtrCB_thunk(vtrTextTrack *track, void *calldata);
int vtrTest(cv::Mat);
bool DrawBox(cv::Mat&);
vtrTextTrack *texttrack;
};
TextDetect::TextDetect() : inifile("vtr.ini")
{
if (vtrInitialize(inifile, vtrCB_thunk, static_cast<void *>(this) ) == -1)
std::cout << "Error: Failure to initialize" << std::endl;
vtrimage = new vtrImage;
}
int TextDetect::vtrTest(cv::Mat imagetest)
{
/*store image data in an image structure*/
}
void TextDetect::vtrCB(vtrTextTrack *track)
{
/*send data to command line from callback */
I've tried copying the data I need a variety of ways and nothing works (this code is a continuation from above):
//texttrack = track;
//texttrack = new vtrTextTrack (*track);
memcpy(texttrack,track,sizeof(*track));
//vtrTextTrackFree(track);
}
void TextDetect::vtrCB_thunk(vtrTextTrack *track, void *calldata)
{
static_cast<TextDetect *>(calldata)->vtrCB(track);
}
This is the member function were I want the data to be used. Texttrack is public member so I might need it outside my class as well (this code is a continuation from above):
bool TextDetect::DrawBox(cv::Mat& tobeboxed)
{
And I get the access violation error at runtime here at this line of code (this code is a continuation from above):
if (texttrack->best->ocrconf > 90)
{
/*do some more stuff*/
}
}
Hopefully I'm understanding this correctly.
It seems to me that the problem is trying to copy those vtrTextTrack structs improperly.
This:
//texttrack = track;
just copies the pointer. If the owner of the struct (probably the caller of the callback function) destroys/deletes the vtrTextTrack, then you're holding on to an invalid pointer.
This one:
memcpy(texttrack,track,sizeof(*track));
will copy all the members of the vtrTextTrack, but will not copy what's being pointed to by it's member pointers (e.g. texttrack->best). Again, if the owner destroys/deletes the track, then you're holding on to invalid pointers.
And since
//texttrack = new vtrTextTrack (*track);
didn't work, I'm guessing that vtrTextTrack doesn't provide a copy constructor.
As for a workaround, first check if your third party library provides a function to copy these structs. If that's not the case (could this be by design?), then you may have to implement one yourself. This might be hard because there might be all kinds of internals that you don't know about. If you don't need the whole vtrTextTrack, I'd say define another struct and store only the information you need. Something along the lines of
SomeType* bestCopier(SomeType* src)
{
SomeType* temp;
/* copy over struct */
return temp;
}
Foo* fooCopier(Foo* src)
{
/*...*/
}
struct myTextTrack
{
public:
myTextTrack(vtrTextTrack* src)
{
//copy over stuff
m_best = bestCopier(src->best);
m_foo = fooCopier(src->foo);
}
private:
/* the members you care about*/
SomeType* m_best;
Foo * m_foo;
}

Best Practice for Scoped Reference Idiom?

I just got burned by a bug that is partially due to my lack of understanding, and partially due to what I think is suboptimal design in our codebase. I'm curious as to how my 5-minute solution can be improved.
We're using ref-counted objects, where we have AddRef() and Release() on objects of these classes. One particular object is derived from the ref-count object, but a common function to get an instance of these objects (GetExisting) hides an AddRef() within itself without advertising that it is doing so. This necessitates doing a Release at the end of the functional block to free the hidden ref, but a developer who didn't inspect the implementation of GetExisting() wouldn't know that, and someone who forgets to add a Release at the end of the function (say, during a mad dash of bug-fixing crunch time) leaks objects. This, of course, was my burn.
void SomeFunction(ProgramStateInfo *P)
{
ThreadClass *thread = ThreadClass::GetExisting( P );
// some code goes here
bool result = UseThreadSomehow(thread);
// some code goes here
thread->Release(); // Need to do this because GetExisting() calls AddRef()
}
So I wrote up a little class to avoid the need for the Release() at the end of these functions.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * Thread() const { return m_T; }
};
So that now I can just do this:
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC.Thread());
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}
What I don't like is that to access the thread pointer, I have to call a member function of ThreadContainer, Thread(). Is there some clever way that I can clean that up so that it's syntactically prettier, or would anything like that obscure the meaning of the container and introduce new problems for developers unfamiliar with the code?
Thanks.
use boost::shared_ptr
it is possible to define your own destructor function, such us in next example: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#com
Yes, you can implement operator ->() for the class, which will recursively call operator ->() on whatever you return:
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * operator -> () const { return m_T; }
};
It's effectively using smart pointer semantics for your wrapper class:
Thread *t = new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
You could also write a conversion function to enable your UseThreadSomehow(ThreadContainer tc) type calls in a similar way.
If Boost is an option, I think you can set up a shared_ptr to act as a smart reference as well.
Take a look at ScopeGuard. It allows syntax like this (shamelessly stolen from that link):
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
Or you could try Boost::ScopeExit:
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// ... // (3) other operations
commit = true; // (4) turn all rollback actions into no-op
}
I would recommend following bb advice and using boost::shared_ptr<>. If boost is not an option, you can take a look at std::auto_ptr<>, which is simple and probably addresses most of your needs. Take into consideration that the std::auto_ptr has special move semantics that you probably don't want to mimic.
The approach is providing both the * and -> operators together with a getter (for the raw pointer) and a release operation in case you want to release control of the inner object.
You can add an automatic type-cast operator to return your raw pointer. This approach is used by Microsoft's CString class to give easy access to the underlying character buffer, and I've always found it handy. There might be some unpleasant surprises to be discovered with this method, as in any time you have an implicit conversion, but I haven't run across any.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
operator ThreadClass *() const { return m_T; }
};
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC);
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}