User Name Password Register
DaniWeb IT Discussion Community
All
What is DaniWeb IT Discussion Community?
You're currently browsing the C++ section within the Software Development category of DaniWeb, a massive community of 429,968 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 2,632 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our C++ advertiser: Programming Forums
Views: 2719 | Replies: 14
Reply
Join Date: Apr 2004
Location: Virginia Beach
Posts: 113
Reputation: liliafan is on a distinguished road 
Rep Power: 5
Solved Threads: 2
liliafan's Avatar
liliafan liliafan is offline Offline
Junior Poster

storing references to classes

  #1  
Jul 7th, 2004
Hi all,

I am not sure how to explain exactly what I am hoping to do here, but I will do my best in the hopes that someone will understand.

I am writing a program that uses a cache, this cache is used with a thread that is seperate from the main program, this works perfectly, the cache is a seperate class.

Now the problem, the cache gets updated hourly from an external file, basically the method is that every minute or so the program checks the stat on the file and if the atime has altered it rebuilds the cache, now I need my thread that is using the cache to use totally transparently the new cache.

Since the building of the new cache every hour is handled by a seperate thread I can't figure out a sane method of updating the class in use by the first thread.

I have tried writing a seperate class called cache_control that works basically to build references ie:

class cache_control {
  public:
     Cache private_cache;
     Cache public_cache;
     void reinit_cache(void);
}

void cache_control::reinit_cache(void) {
   private_cache.read_input_file();
   Cache & pubic_cache = private_cache;
}

Please excuse the roughness of this code it is just an example of the type of thing I am attempting to do.

As you see I am making 2 caches the private and the public the public_cache is just a reference to the private_cache object and when my thread is started it is passed a reference to the main cache_control object from main() and it uses the public_cache it access its methods and data, that way when I need to rebuild the cache I just reinit_cache the private_cache and it then points public_cache to the new instance of private_cache.

I hope you are with me so far.

The problem I have here is that firstly I am creating the object Cache public_cache before I get the chance to declare it as a reference and I don't think this is allowed (I may be wrong) and secondly, I think that perhaps having a reference to a class that references a class that isn't inherited, is perhaps a dangerous thing to do, and thirdly it just plain doesn't seem to work.

I am basically looking for a good suggestion from someone on a better way of doing this, I though perhaps I should make my Cache class in inherited class from cache_control but the way I see it is that will just make it a little cleaner it won't actually make it work, I also considered creating a global vector something like:

vector<cache> global_cache;

Then when I need to rebuild the cache I simply build a new instance of the cache delete the instance currently in the vector and add the new one, but I think perhaps that will create some more problems in itself not to mention the fact that my test programs using a vector with type <cache> all seem to die at run time no matter that I do with them.

What I am hoping to avoid is having to kill the thread and restart it with a new copy of the data is the program itself is a fairly high demand searchengine and by killing the thread I would have to kill all client connections.

Any suggestions would be very welcome I have been pulling my hair out on this one for a couple of days, if anymore explaination of what I am hoping to do is needed please let me know.

Thanks

Ben
Application development, webhosting, and much more: www.webcentric-hosting.com
AddThis Social Bookmark Button
Reply With Quote  
Join Date: Jun 2004
Location: Marin, CA, USA
Posts: 434
Reputation: Chainsaw is an unknown quantity at this point 
Rep Power: 5
Solved Threads: 10
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: storing references to classes

  #2  
Jul 7th, 2004
So you have a cache maintained by the main process thread and one or more other threads that access the cache (you said one, but heck). And your question, if I understand it, is:

"How can I prevent the non-main threads from accessing the cache while it is being rebuilt by the main thread?"

So, if that is the basic question then.....

The way you do that is with a 'critical section'. A 'critical section' can only be in use by one thread at a time. If another thread wants access to the critical section, it is blocked until the critical section becomes free.

All real os' have this, here's how it might look in Windows:

CRITICAL_SECTION threadLock;
::InitializeCriticalSection( &threadLock ); // initialize this ONCE
...

int cache::ReadCache()
{
    int rtn;

        // to get access to the cache, call this:
    ::EnterCriticalSection( &threadLock );

        // now you are the ONLY thread in this code, others will wait for you...
    rtn = vartogetfromthecache;

        // you must leave the critical section, or things stay locked.
    ::LeaveCriticalSection( &threadLock );

    return rtn;
}

Since threads will wait, you want the critical section to NOT TAKE LONG, or it will gum everything up. Instead, use it as a wrapper around accesses to the data. When updating from the database, you will want to get the data all ready to go (reading the disk OUTSIDE the critical section since thats slow), and then enter the critical section, copy in your new data, end exit the critical section.
Reply With Quote  
Join Date: Jun 2004
Location: Marin, CA, USA
Posts: 434
Reputation: Chainsaw is an unknown quantity at this point 
Rep Power: 5
Solved Threads: 10
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: storing references to classes

  #3  
Jul 7th, 2004
Although I realized after posting that, what you WANTED to know was how to make a reference to a class....

AClass classInstance;
AClass *pClassInstance; // pointer to the class
AClass &rClassInstance; // reference to the class

references are really pointers internally, but with the syntactic nicety that you don't use ->, but just use .

classInstance.SetVal(12);
pClassInstance->SetVal(12);
rClassInstance.SetVal(12);

Like a pointer, a reference must refer to something:

pClassInstance = &classInstance; // pClassInstance now POINTS TO classInstance
rClassInstance = classInstance; // rClassInstance now REFERS to classInstance

A reference has no space allocated for it's object, the same as a pointer.
Reply With Quote  
Join Date: Apr 2004
Location: Virginia Beach
Posts: 113
Reputation: liliafan is on a distinguished road 
Rep Power: 5
Solved Threads: 2
liliafan's Avatar
liliafan liliafan is offline Offline
Junior Poster

Re: storing references to classes

  #4  
Jul 7th, 2004
Originally Posted by Chainsaw
Although I realized after posting that, what you WANTED to know was how to make a reference to a class....

AClass classInstance;
AClass *pClassInstance; // pointer to the class
AClass &rClassInstance; // reference to the class

references are really pointers internally, but with the syntactic nicety that you don't use ->, but just use .

classInstance.SetVal(12);
pClassInstance->SetVal(12);
rClassInstance.SetVal(12);

Like a pointer, a reference must refer to something:

pClassInstance = &classInstance; // pClassInstance now POINTS TO classInstance
rClassInstance = classInstance; // rClassInstance now REFERS to classInstance

A reference has no space allocated for it's object, the same as a pointer.

Okay that is looking a lot like what I was looking for, so is it possible to define the pointer (reference) to the class and then actually decide where it point it to?

ie:

class SomeClass {
   public:
      Aclassname actualclass;
      Aclassname *pointerclass;
   public:
      void makepointer(void) {
         pointerclass = &actualclass;
      }
}

On looking at your code that looks like it is okay, which is exactly what I wanted, for the other half though, if later on I wanted to point the pointer to a different class without deleting the pointer how would I do that?

ie

void point_else_where(void) {
   delete pointerclass;
   pointerclass = &newactualclass;
}

As you can see I know exactly what I am wanting to do it is really all a matter of syntax, I haven't been programming C++ for long enough to have encountered a lot of this stuff.

Thanks for the help on the first part if you can give me a prod in the right direction on the second part I would be eternally grateful

Thanks again

Ben
Application development, webhosting, and much more: www.webcentric-hosting.com
Reply With Quote  
Join Date: Jun 2004
Location: Marin, CA, USA
Posts: 434
Reputation: Chainsaw is an unknown quantity at this point 
Rep Power: 5
Solved Threads: 10
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: storing references to classes

  #5  
Jul 8th, 2004
Since you said "pointerclass = &actualclass;", you don't want to try to DELETE the pointer pointerclass, because it doesn't point to allocated space!

So, two ways suggest themselves:

// **METHOD ONE**
AClassname c[2];
AClassname* pCurrentOneInUse;
int whichClassIsInUse;
...
whichClassIsInUse = 0;
pCurrentOneInUse = c[whichClassIsInUse];
...
void swapclasses()
{
    // here, we assume you've filled in the NON-current AClassname with the
    // new data; that's a bit clunky because you have to do a
    // whichClassIsInUse test like I do here to pick the class NOT in use.
    // If I were a hacker, I might just say (!whichClassIsInUse), but
    // that isn't as clear.  :-)
    if (whichClassIsInUse == 0)
        whichClassIsInUse =  1;
    else
        whichClassIsInUse = 0;
    pCurrentOneInUse = c[whichClassIsInUse];
}
Method one has the advantage that there is no memory allocations, everything is static. That might be a tad faster, all other things being equal. It just seems kinda clunky to me, though.

//***METHOD TWO***
AClassname* pCurrentOneInUse;
...
pCurrentOneInUse = NULL;
...
void swapclasses( AClassname* withThis )
{
    // here, we assume you have a local var that you filled in the new data
    // with and passed into this routine
    delete pCurrentOneInUse;
    pCurrentOneInUse = new AClassname( *withThis ); // use copy constructor
    // or, if no copy constructor, copy the contents HERE
    // or, the caller could do the new and here you just point to the space
}
Reply With Quote  
Join Date: Apr 2004
Location: Virginia Beach
Posts: 113
Reputation: liliafan is on a distinguished road 
Rep Power: 5
Solved Threads: 2
liliafan's Avatar
liliafan liliafan is offline Offline
Junior Poster

Re: storing references to classes

  #6  
Jul 8th, 2004
Chainsaw, now that looks perfect I am gonna start playing around with those methods now

As promised you have my eternal gratitude!!

Thanks again

Ben
Application development, webhosting, and much more: www.webcentric-hosting.com
Reply With Quote  
Join Date: Apr 2004
Location: Virginia Beach
Posts: 113
Reputation: liliafan is on a distinguished road 
Rep Power: 5
Solved Threads: 2
liliafan's Avatar
liliafan liliafan is offline Offline
Junior Poster

Re: storing references to classes

  #7  
Jul 8th, 2004
Okay I am having a bit of a problem now, this is basically the test class I have written:

Header:
class g_cache{
public:
    keyword_cache* Kcache;
    keyword_cache referenced_kcache;
    SKU_cache Scache;
    void Set_Kcache_Reference(void);
public:    
    g_cache();
    ~g_cache();
};

Main:
g_cache::g_cache()
{
   g_cache::Set_Kcache_Reference();     
}


g_cache::~g_cache()
{
}

void g_cache::Set_Kcache_Reference(void)
{
   referenced_kcache.read_output_file();
   keyword_cache Kcache = referenced_kcache;
   string word = "black";
   
   cout << "Test1" << endl; 
   referenced_kcache.find_keyword(word);   

   cout << "Test2" << endl; 
   Kcache.find_keyword(word);      
}

This bit works when I initalise the class the output is correct both times.

However:

  g_cache caches; 

  string word = "black";
  caches.Kcache.find_keyword(word);

Doesn't even compile it gives the following error:

vsearch.cpp: In function `int main(int, char**)':
vsearch.cpp:293: error: request for member `find' in `caches.g_cache::Kcache',
which is of non-aggregate type `keyword_cache*'

Any suggestions.

Thanks

Ben
Application development, webhosting, and much more: www.webcentric-hosting.com
Reply With Quote  
Join Date: Jun 2004
Location: Marin, CA, USA
Posts: 434
Reputation: Chainsaw is an unknown quantity at this point 
Rep Power: 5
Solved Threads: 10
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: storing references to classes

  #8  
Jul 8th, 2004
Kcache is a pointer, so you need -> rather than .

caches.Kcache->find_keyword(word);
Reply With Quote  
Join Date: Apr 2004
Location: Virginia Beach
Posts: 113
Reputation: liliafan is on a distinguished road 
Rep Power: 5
Solved Threads: 2
liliafan's Avatar
liliafan liliafan is offline Offline
Junior Poster

Re: storing references to classes

  #9  
Jul 9th, 2004
Originally Posted by Chainsaw
Kcache is a pointer, so you need -> rather than .

caches.Kcache->find_keyword(word);

That will allow it to compile but it causes a segfault when it does compile, which is interesting since if I use the actual class that is pointed to it runs fine, it is only when I use the pointer class that it will segfault.

Ben
Application development, webhosting, and much more: www.webcentric-hosting.com
Reply With Quote  
Join Date: Jun 2004
Location: Marin, CA, USA
Posts: 434
Reputation: Chainsaw is an unknown quantity at this point 
Rep Power: 5
Solved Threads: 10
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: storing references to classes

  #10  
Jul 9th, 2004
Do you ever set Kcache = &referenced_cache?

A segment fault means the pointer is pointing into random memory.
Reply With Quote  
Reply

Only community members can participate in forum threads. You must register or log in to contribute.

DaniWeb C++ Marketplace
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)

 

Thread Tools Display Modes

Other Threads in the C++ Forum

All times are GMT -4. The time now is 11:45 pm.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC