circular dependency...

R

Rob Clark

Hi,

I have an issue which is the ordinary and always recurring circular
dependency - but I do not know how to resolve it :-( The usual forward
declaration does not help...

I have a client that uses a resource. As a consequence of using the
resource, the resource later receives an asynchronous notification (from an
underlying layer, e.g. OS). This notification should then be forwarded to
the Client that owns the resource.

In code this looks something:

int main()
{
Resource resource; // Define the resource
Client client(&resource); // Configure the client to own the resource
client.Execute(); // Execute operation, which in turn uses the
resource

RunEventLoopForever();
}


class Resource
{
Client* m_client;
public:
void SetClient(Client* client)
{
m_client = client;
}

void Use()
{
// Use this resource
// DoSomethingInteresting()
}
void AsyncNotification()
{
m_client->Notify();
}
};

class Client
{
Resource* m_resource;
public:
Client(Resource* res) : m_resource(res)
{
m_resource->SetClient(this);
}
void Execute()
{
m_resource->Use();
}
void Notify()
{
// Handle notification
// m_resource->Whatever()
}
};

What should I do to resolve this issue?
Complete redesign? Rather not - I like this simple design (besides it
doesn't work...)
Introducing something in between to break the dependency? If so - what?

Thanks in advamce!
/Rob
 
N

Neelesh Bodas

Rob said:
class Resource
{
Client* m_client;
public:
void SetClient(Client* client)
{
m_client = client;
}

void Use()
{
// Use this resource
// DoSomethingInteresting()
}
void AsyncNotification()
{
m_client->Notify();
}
};

class Client
{
Resource* m_resource;
public:
Client(Resource* res) : m_resource(res)
{
m_resource->SetClient(this);
}
void Execute()
{
m_resource->Use();
}
void Notify()
{
// Handle notification
// m_resource->Whatever()
}
};

What should I do to resolve this issue?

Donot define member functions inside the class. Simply declare them.
Define them outside the class. Use inline if you want them to be
inlined. Then simply declare the required class.

//header file Resource.h
class Client;
class Resource
{
Client* m_client;
public:
void SetClient(Client* client);
void Use();
void AsyncNotification();
};

// definitions will go in Resource.cpp. Include Resource.h there.

HTH.
 
J

John Carson

Rob Clark said:
Hi,

I have an issue which is the ordinary and always recurring circular
dependency - but I do not know how to resolve it :-( The usual
forward declaration does not help...

I have a client that uses a resource. As a consequence of using the
resource, the resource later receives an asynchronous notification
(from an underlying layer, e.g. OS). This notification should then be
forwarded to the Client that owns the resource.

In code this looks something:

Plainly the Resource and Client classes must be declared prior to main(),
quite apart from any circular dependency issues.
int main()
{
Resource resource; // Define the resource
Client client(&resource); // Configure the client to own the
resource client.Execute(); // Execute operation, which in turn
uses the resource

RunEventLoopForever();
}


class Resource
{
Client* m_client;
public:
void SetClient(Client* client)
{
m_client = client;
}

void Use()
{
// Use this resource
// DoSomethingInteresting()
}
void AsyncNotification()
{
m_client->Notify();
}

This is where your fundamental problem lies. You are calling a member
function of Client before the client class has been defined. The solution is
to only declare AsyncNotification here and define it later.
};

class Client
{
Resource* m_resource;
public:
Client(Resource* res) : m_resource(res)
{
m_resource->SetClient(this);
}
void Execute()
{
m_resource->Use();
}
void Notify()
{
// Handle notification
// m_resource->Whatever()
}
};

What should I do to resolve this issue?
Complete redesign? Rather not - I like this simple design (besides it
doesn't work...)
Introducing something in between to break the dependency? If so -
what?
Thanks in advamce!
/Rob

The following compiles:

class Client;

class Resource
{
Client* m_client;
public:
void SetClient(Client* client)
{
m_client = client;
}

void Use()
{
// Use this resource
// DoSomethingInteresting()
}
void AsyncNotification();
};

class Client
{
Resource* m_resource;
public:
Client(Resource* res) : m_resource(res)
{
m_resource->SetClient(this);
}
void Execute()
{
m_resource->Use();
}
void Notify()
{
// Handle notification
// m_resource->Whatever()
}
};

void Resource::AsyncNotification()
{
m_client->Notify();
}


int main()
{
Resource resource; // Define the resource
Client client(&resource); // Configure the client to own the resource
client.Execute(); // Execute operation, which in turn uses the
resource

//RunEventLoopForever();
}
 
R

Rob Clark

Oh so obvious when you have the answer - thank you both guys, Neelesh and
John!
/Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top