I implemented a kind of "thread local singleton" using pthread TLS, and i wondered how (and when) i could possibly delete the pthread_key_t in this case, because as it is now, the memory used by the TLS key will never be free'd.
The intended usage of this is to let a class A derive from ThreadLocalSingleton<A> which makes A a thread local singleton, assuming that A has only private constructors and ThreadLocalSingleton<A> is a friend of A.
Oh and also - do you see any problems with that implementation; did i overlook anything important?
#include <pthread.h>
#include <iostream>
template <class T>
class ThreadLocalSingleton
{
private:
static pthread_key_t tlsKey;
static pthread_once_t tlsKey_once;
static void tls_make_key()
{
(void)pthread_key_create(&ThreadLocalSingleton::tlsKey, ThreadLocalSingleton::tls_destructor);
}
static void tls_destructor(void* obj)
{
delete ((T*)obj);
pthread_setspecific(tlsKey, NULL); // necessary or it will call the destructor again.
}
public:
/*
* A thread-local singleton getter, the resulted object must never be released,
* it is auto-released when the thread exits.
*/
static T* getThreadInstance(void)
{
pthread_once(&tlsKey_once, ThreadLocalSingleton::tls_make_key);
T* instance = (T*)pthread_getspecific(tlsKey);
if(!instance)
{
try
{
instance = new T;
pthread_setspecific(tlsKey, instance);
}
catch (const char* ex)
{
printf("Exception during thread local singleton init: %s\n",ex);
}
}
return instance;
}
};
template <class T>
pthread_key_t ThreadLocalSingleton<T>::tlsKey;
template <class T>
pthread_once_t ThreadLocalSingleton<T>::tlsKey_once = PTHREAD_ONCE_INIT;
Your implementation looks very elegant.
According to the Open Group Specification of pthread_key_create, you don't have to set the reference to NULL in the destructor:
An optional destructor function may be associated with each key value. At thread exit, if a key value has a non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument.
I think this also implies that the key object itself will be autodestroyed by pthread. You only have to take care of what's stored behind the key, which is precisely what your delete ((T*)obj); does.
Related
I have a project for ESP32 (Vscode/platformIO) with this code working:
BCls receives in its constructor a pointer to an instance of ACls and assign it to its private _a.
So in main.cpp, I just create and instance of ACls, then inject a pointer to it into the constructor of BCls:
main.cpp
#include "ACls.h"
ACls aa;
#include "BCls.h"
BCls bb(aa);
void setup() {
bb.doSomething("hello");
}
BCls.h
#include "ACls.h"
class BCls {
public:
ACls *_a;
//ctors
BCls();
BCls(ACls *aa);
}
BCls.cpp
#include "BCls.h"
#include "ACls.h"
BCls::BCls() {
}
BCls::BCls(ACls *aa) {
_a = aa;
}
The problem:
But now I need to modify it so that, if BCls does not receive in its constructor an ACls instance, it must instantiate it internally and assign it to _a.
I tried this but it does not work (compiles ok but fails in runtime):
main.cpp
#include "BCls.h"
BCls bb;
void setup() {
bb.doSomething("hello");
}
BCls.h
class BCls {
public:
ACls *_a;
//ctors
BCls();
BCls(ACls *aa);
}
BCls.cpp
#include "ACls.h"
BCls::BCls() {
//how to instantiate here an object of class ACls and assign a pointer to it to BCls._a??
//I tried this but its not working:
ACls aTmp;
_a = &aTmp;
}
BCls::BCls(ACls *aa) {
_a = aa;
}
the exception is
rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1284
load:0x40078000,len:12808
load:0x40080400,len:3032
entry 0x400805e4
So, how should this be done?
MORE INFO:
I will try to explain deeper why I want to do this:
Lets say I have 3 classes:
SdCls -> manages everything related to a SD card module.
GpsCls -> manages everything related to a gps module.
SensorCls -> manages everything related to a temperature sensor.
And lets say both GpsCls and SensorCls, need to log some data on the sd card.
and also the project's main file needs to use the sd card to read files or whatever.
So right now, in projects main file, I instantiate SdCls, then instantiate GpsCls and SensorCls, passing the SdCls instance to their constructors. so now I can use the SD card in the projects main file, and both the gpsCls and SensorCls can use that same instance of SdCls to do their things. And everyone is happy.
But now I want these classes to be reusable in other projects. and lets say in another project, the only one that needs to access the SD card is the GpsCls. My idea with this was that, instead of instantiating the SdCls in the project main file, that I could just create the GpsCls object calling its empty constructor, and then let the GpsCls class instantiate the SdCls object it needs (as it will only be used by GpsCls)
I hope this is clearer now...
The problem you are facing is a result of the lifetime of the ACls object you want to keep a pointer to in BCls, by declaring it in the constructor, when the constructor returns, aTmp goes out of scope and is destroyed and the pointer saved no longer points to a valid ACls object.
There are a few options to solve this:
If you can afford creating a ACls for every BCls object, simply create a member ACls:
class BCls {
ACls _m_a;
ACls *_a;
public:
BCls() : _a(&_m_a) { }
BCls(ACls *aa) : _a(aa) { }
};
If you only need to create one BCls or they can share ACls object, you can declare the aTmp as static:
class BCls {
ACls *_a;
public:
BCls() {
static ACls aTmp; // Note this will be shared for all BCls objects that use this constructor
_a = &aTmp;
}
BCls(ACls *aa) : _a(aa) { }
};
If you cannot do either of the above, the best bet is to dynamically allocate ACls (or you could allocate from a static pool but that involves more work that might not be worth it on something like an ESP32; also remember to delete the object in the destructor for the BCls object if needed to not leak memory):
class BCls {
ACls *_a;
public:
BCls() {
_a = new ACls();
}
BCls(ACls *aa) : _a(aa) { }
};
For example I'm having a class with three overloaded methods like this:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
// Method implementation.
}
}
My question is when I call the sum method of MyClass by passing any value (integer, string or object) it should invoke only third method (with object type input parameter)
class MainClass
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
obj.sum(10);
obj.sum("X")
}
}
You said "without type casting" but you can't, because you need some way to indicate to the compiler which version to call, and the runtime uses the type it sees to do that bit. Boxing the int as an object means the compiler will pick the object version
sum(1);//call int version
sum((object)1); //call object version
sum((string)(object)"1"); //call string version
sum((object)(int)(object)1); //call object version
First of all, let me say that if you sometimes want to call one version of the sum function when working with ints and sometimes want to call another, overloading probably isn't the right tool to use. Overloading works best when you are implementing conceptually the same operation for a number of different types, and you want the compiler to figure out automatically which function is the right one to call for each type; if you need more manual control over which function is called, you're probably better off using different names.
That said, if you're sure that this is what you want to do, you could implement the overloaded version for object in terms of another function in the public interface, as in:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
sum_object(o);
}
int sum_object(object o)
{
// Method implementation for objects
}
}
Then, when you want to apply the object version to int and string objects, you just call sum_object directly instead.
I have created a new managed, reference class in C++ cli. And now I want to overload equality of objects of this class.
public ref class DerivedFromObject {
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (const DerivedFromObject%, const DerivedFromObject%);
static bool operator== (const DerivedFromObject%, const DerivedFromObject%);
}
As far as I know from C#, operator!= calls operator==, that calls Equals, which refers to GetHashCode.
bool DerivedFromObject::operator==(const DerivedFromObject % a, const DerivedFromObject % b)
{
a.Equals((Object^)%b); // Error
}
In the snippet above, Equals and GetHashCode cannot be called on a const object, that's why I cannot call Equals from operator==.
How can I mark method that doesn't change the object in C++ cli? Or What the most appropriative way to define equality chain?
There's two things here:
.Net doesn't really have the concept of const in the way that C++ does. C++/CLI will enforce the rules that C++ has, but since .Net doesn't use it, no library methods are declared const, so you'll have problems calling just about any method. Rather than being explicitly declared like in C++, it's just by convention that methods like equals don't modify their parameters.
Since you used const%, I think you were trying to parallel the C++ convention of passing const& parameters. % is more similar in usage to ** double pointer than to &: You pass things parameters as % (or ^% for reference types) when the method can assign a value to the parameter, and it should be available to the calling method.
Here's how I would implement this:
public ref class DerivedFromObject : IEquatable<DerivedFromObject> {
virtual bool Equals(DerivedFromObject^ other);
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (DerivedFromObject^, DerivedFromObject^);
static bool operator== (DerivedFromObject^, DerivedFromObject^);
}
One other thing you said:
...Equals, which refers to GetHashCode.
Be careful here, because it is possible for unequal objects to have the same hash code.
GetHashCode will need to evaluate everything, and then if the hash codes are equal, then Equals need to evaluate everything again to be sure they're actually equal. It'll probably be more efficient to not look at the hash code, just compare the objects field by field, and bail out as soon as they're not equal.
I have a c++-cli class Locator with a function Locate that takes a lot of memory while it is running. At the end of running, most of the memory is released withing the function by releasing the pointers, but there is still some memory that is not deallocated and if I run the program continuously in a lopp, it stacks up. Is there a way to completely remove all the memory that was allocated using the destructor/constructor at the end of the function each time?
public ref class Locator
{
public:
Locator() { }
~Locator() { }
Dictionary<String^, array< Byte >^>^ Locate(Dictionary<String^, String^>^ imgParms)
{ ..... }
private:
int m_HP;
int main ()
{
Locator r;
Dictionary<String^,String^>^ myDictionary = gcnew Dictionary<String^,String^>();
Dictionary<String^,List<array<Byte>^>^>^ myResult1 = gcnew Dictionary<String^,List<array<Byte>^>^>();
myResult1=r.Locate(myDictionary,0);
return 0;
}
Call delete() on the objects you create(just like plain C++). Simply dereferencing the pointer will leave the object for the garbage collector to dispose. Ordinarily this is fine, but if you use a lot of memory in your application, you dont want the wait for the GC to release memory. Ensure that your destructors delete all objects allocated by their respective destructors. This is exactly the same as plain C++. C++/CLI classes implicitly inherit the IDisposable interface and the destructors are wrappers for Dispose() so you dont have to define dispose() seprately(If i remember correctly; you can't do that anyway).
I'm new to C++/CLI and I'm wondering what is "best practice" regarding managed type data members. Declaring as handle:
public ref class A {
public:
A() : myList(gcnew List<int>()) {}
private:
List<int>^ myList;
};
or as a value:
public ref class B {
private:
List<int> myList;
};
Can't seem to find definitive advice on this.
When writing managed C++ code, I'm in favor of following the conventions used by the other managed languages. Therefore, I'd go with handles for class-level data members, and only use values (stack semantics) where you'd use a using statement in C#.
If your class member is a value, then replacing the object entirely means that the object would need a copy constructor defined, and not many .NET classes do. Also, if you want to pass the object to another method, you'll need to use the % operator to convert from List<int> to List<int>^. (Not a big deal to type %, but easy to forget, and the compiler error just says it can't convert List<int> to List<int>^.)
//Example of the `%` operator
void CSharpMethodThatDoesSomethingWithAList(List<int>^ list) { }
List<int> valueList;
CSharpMethodThatDoesSomethingWithAList(%valueList);
List<int>^ handleList = gcnew List<int>();
CSharpMethodThatDoesSomethingWithAList(handleList);
It all depends on the lifetime. When you have a private member which lives exactly as long as the owning class, the second form is preferable.
Personally, I would use the second form. I say this because I use frameworks that are written by other teams of people, and they use this form.
I believe this is because it is cleaner, uses less space, and is easier for the non-author to read. I try to keep in mind that the most concise code, while still being readable by someone with minimal knowledge of the project is best.
Also, I have not encountered any problems with the latter example in terms of readability across header files, methods, classes, or data files ...etc
Though I'm FAR from an expert in the matter, that is what I prefer. Makes more sense to me.
class AlgoCompSelector : public TSelector {
public :
AlgoCompSelector( TTree *tree = 0 );
virtual ~AlgoCompSelector(){ /* */ };
virtual void Init(TTree *tree);
virtual void SlaveBegin(TTree *tree);
virtual Bool_t Process(Long64_t entry);
virtual void Terminate();
virtual Int_t Version() const { return 1; }
void setAlgo( Int_t idx, const Char_t *name, TTree* part2, TTree* part3 );
void setPTthres( Float_t val );
void setEthres( Float_t val );
private:
std::string mAlgoName[2]; // use this for the axis labels and/or legend labels.
TTree *mPart1;
TTree *mPart2[2], *mPart3[2]; // pointers to TTrees of the various parts
TBranch *mPhotonBranch[2]; // Used branches
TClonesArray *mPhotonArray[2]; // To point to the array in the tree
for example