Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
davidwyandgg's avatar
davidwyandgg
Explorer
12 years ago

Reference Counting and Ptr<>

Hey Rift Peeps.

In reading through the OVR docs there is mention of reference counting. And in looking at the example code I see that the OVR::Ptr<> template is used throughout. I was wondering if the SDK reference counting then depends on the use of the OVR::Ptr<> template, or is it internal to the device (and device manager) objects themselves when they are created?

For example, when using the DeviceManager class could I do something like this (just an example thrown together here)?

class OVRManager
{
protected:
OVR::DeviceManger* mDeviceManager;

public:
OVRManager()
{
mDeviceManager = OVR::DeviceManager::Create();
}
virtual ~OVRManager()
{
mDeviceManager->Release();
}
};


Or is using the OVR::Ptr<> template a requirement for working with all device objects, including the manager?

Thanks!

- Dave

6 Replies

  • Based upon another reading of the Ptr<> template, it appears that I would just need to add an AddRef() call to the device object and I would be good. The Release() then performs the reference decrement.

    So I would guess that obtaining an object pointer does not perform any automatic reference counting.

    - Dave
  • Sorry to spam the thread. When I added an AddRef() call to my newly created DeviceManager I end up hanging in my debug build when I exit my app. The hanging appears to occur somewhere from here:

    OculusTest_DEBUG.dll!OVR::Win32::DeviceManagerThread::Run()  Line 183 + 0x2b bytes


    So I guess the AddRef() is not needed after all when handling the releasing directly. Without adding that AddRef() to my code in the OP, I don't get the hang.

    - Dave
  • Hey Dave,

    Sorry for the delay. Although we recommend people use the "Ptr<>" smart-pointer, you are not required to use it. If you just want to use a regular pointer the code that you posted would work.

    Internally the object would still be reference counted. You do not have to manually call "AddRef()".

    However, it may be a good idea to make sure the pointer you create is not null, since you will lose that functionality if not using the smart-pointer template.

    Hope that helps.

    - Andres
  • mikeant's avatar
    mikeant
    Honored Guest
    Hi David,

    I wanted to explain some behavior related to DeviceManagerThread::Run(). The hang you might have experienced on shutdown makes sense if DeviceManager was not released due to an extra AddRef; all references to this object must be released before the app can exit. Generally speaking, all OVR objects must be released to avoid memory leaks and ensure cleanup.

    All OVR Device objects start out with the Reference Count of 1, while calling Release() reduces them to 0, freeing the memory and resources. Normally this is done automatically through ~Ptr<>.

    One quirk worth mentioning about the Ptr<> is that it always AddRefs() on assignment of either raw pointer or another Ptr<>, and only avoids that if an object is assigned by reference. This assignment is useful when initializing it with a new object, to prevent RefCount from jumping to 2 and leaking later. This is why you will sometimes see the following code:
     Ptr<DeviceManager> manager = *DeviceManager::Create();

    The extra asterisk above ensures that RefCount stays doesn't get incremented to two. This is, of course, only required on the very first assignment of the object. Doing reference counting this way (as opposed to initializing them at ref-count of 0) has the benefit of allowing both raw and smart pointers to be passed as arguments in the program without worrying whether the object is still alive after the function call returns.

    Going back to device manager... DeviceManager class creates an internal thread used to service sensor input and this thread remains alive until the manager is released. On app exit shutdown OVR::System::Destroy waits for all OVR threads to exit - this is necessary to clean up all memory allocations and unwind destructors (Killing threads would be a really bad practice). If the device manager thread is still alive, this function will not exit.

    Cheers,
    Michael
  • Hi Michael.

    Thanks for the additional information. That sounds like some great stuff to include in a future release of the SDK docs.

    In Torque 3D we generally put our own wrapper around the 3rd party libraries to expose things in a game engine friendly way, so it would be rare to be passing around OVR SDK pointers to other engine components. But certainly we want everything to be clean when it comes time to shutdown, so being aware of how the internals are kept track of is important.

    Thanks!

    - Dave