| |

VerySource

 Forgot password?
 Register
Search
View: 3889|Reply: 20

Structural design issues, experts please come in

[Copy link]

2

Threads

13

Posts

12.00

Credits

Newbie

Rank: 1

Credits
12.00

 China

Post time: 2020-12-14 10:30:01
| Show all posts |Read mode
Figure:
========== ========= ======== ========
| CDevice1 | | CDevice2| |CDevice3| ... |CDeviceN|
========== ========= ======== ========
      ↑ ↑ ↑ ↑
      ↓ ↓ ↓ ↓
================================================= =====
| CWhat? |
| |
================================================= =====
...Is this: each device class can be understood as a driver of the operating system!!
CWhat is the OS, and it needs to achieve "two-way" communication with the driver: that is, CWhat must actively adjust the Device, and the Device must also actively report to CWhat when an interrupt occurs.
This analogy is very similar to the current situation, which is the two-way interaction design problem between the underlying device and the upper OS.

In fact, there are two purposes for this consideration:
1. When the hardware of a certain type of device is updated, I can easily replace CDeviceX without modifying other modules of the system (i.e. loose coupling)
2. The heart-level control core of CWhat should be kept simple on a loose basis and not complicated.
Reply

Use magic Report

0

Threads

70

Posts

42.00

Credits

Newbie

Rank: 1

Credits
42.00

 China

Post time: 2020-12-14 19:30:01
| Show all posts
Sorry, you can look at this code and talk about why it is not suitable for you


class IDevice
{
public:
virtual void OnEvent(void*) = 0;
}

class CDevice1
{
private:
void OnInterrupt(void* parameter)
{
CKernel::GetInstance()->OnDeviceInterrupt(parameter);

}

public:
virtual void OnEvent(void*)
{
}

}

class CDevice2
{
public:
void OnInterrupt(void*)
{

}

virtual void OnEvent(void*)
{
}
}

class IDeviceInterrupt
{
public:
virtual void OnDeviceInterrupt(void*) = 0;
virtual void RegisterDevice(IDevice *ptr, IDevice *root) = 0;
virtual void UnRegisterDevice(IDevice *ptr) = 0;
}


class CKernel: public IDeviceInterrupt
{
public:
static IDeviceInterrupt *GetInstance()
{
if(0 == pThis) {
pThis = new CKernel;
}
To
return pThis;
}

public:
virtual void OnDeviceInterrupt(void *)
{
// TODO: add process device's interrupt code at here.
// this interface call by CDevice?
}

virtual void RegisterDevice(IDevice *ptr, IDevice *root)
{
// TODO: add register a new or replace device code at here.
// this interface call by CDevice?

if(root != 0) {
UnRegisterDevice(root);
}

InternalRegister(ptr);
}

virtual void UnRegisterDevice(IDevice *ptr)
{
// TODO: add unregister a device code at here.
// this interface call by CDevice?
}


private:
To
void fire_event(void* parameter)
{
IDevice *obj;
for(...)
{
obj = ...;
obj->OnEvent(parameter);
}
}
To
static IDeviceInterrupt * pThis;
}
Reply

Use magic Report

0

Threads

15

Posts

13.00

Credits

Newbie

Rank: 1

Credits
13.00

 China

Post time: 2020-12-15 00:45:01
| Show all posts
Is this possible? Since there are so many devices dealing with CWhat and the differences are so different, can you abstract a class separately, such as IDevControl, to achieve different control of each device, that is, CWhat delegates the control of each Device Give this device control interface to complete:

struct IDevControl
{
     LRESULT ControlDevice(enum DevTypeId id, CWhat* pWhat, ...//Other parameters, can be very broad);
};
In this way, different IDevControl interfaces are implemented for different devices, such as:
class Dev1Controller: public IDevControl{....};
class Dev2Controller: public IDevControl{....};

Maintain an IDevControl reference table inside CWhat, when processing different devices, according to the device Id, entrust the corresponding IDevControl to complete, because ControlDevice(...pWhat...) refers to CWhat, so you can also call CWhat methods to assist in control The completion.

The callback of each Device to CWhat can also be implemented similarly, for example, let CWhat expose the IInterruptHandler interface
struct IInterruptHandler
{
    HRESULT ServiceDevice(enum DevTypeId id, ...);
}

In this way, when CWhat receives interrupt requests from different devices, it delegates to the corresponding Interrupt Handler to process
Reply

Use magic Report

0

Threads

70

Posts

42.00

Credits

Newbie

Rank: 1

Credits
42.00

 China

Post time: 2020-12-15 09:15:01
| Show all posts
I looked at your original post and found that you have a problem, that is, you said that you cannot abstract a common interface class for all specific devices. This is wrong. The common interface class is to describe the same part of a class of affairs. , Since there are multiple devices in your system, then all devices must have some common features that everyone has, otherwise they are not of the same type. Personally suggest that you divide your device features into the following. Public features, if you still insist on your point of view, I think your problem is not a problem solved by object-oriented (say one more sentence, are you born in C?)
Reply

Use magic Report

2

Threads

13

Posts

12.00

Credits

Newbie

Rank: 1

Credits
12.00

 China

 Author| Post time: 2020-12-15 14:00:01
| Show all posts
to:爱德华德
Haha, the code is written in great detail. Dude has worked hard. Tell me about my views, I hope I can advise you more if it is wrong.
Let me talk about the single item first. In this case, I do not support or oppose it.
Not supported: First, it is too penetrating, and it is not a good idea to appear in every device. For your code, I prefer this way:
class CDevice1:public IDevice //No misunderstanding, right? Huh
{
public:
CDevice1(IDeviceInterrupt* kernalFace);
protected:
IDeviceInterrupt* _kernalFace;
void OnInterrupt(void* parameter)
{
  _kernalFace->OnDeviceInterrupt(parameter);
}
...
}

int main()
{...; IDevice* devFace1 = new CDevice1(CKernel::GetInstance()); ...}
For the two, you must bother to consider synchronization issues. Too many devices have their own threads, and if they all call back to CWhat, synchronization.. For single
In terms of not only locking synchronization in the construction and destructuring, but also considering more complicated synchronization problems in OnDeviceInterrupt(void*): You can't lock it all at once, so that more than 10 threads are waiting in line during concurrency, which is too inefficient. , Can't do this.
No objection: A single piece is a scorpion shit-only one, the resource consumption is small, and many calls are simple to operate. If you can handle the synchronization problem, it is also a good choice.

Let’s talk about the problem of IDevice. We can’t get a very beautiful IDevice just because we call it "device".
This is ideal. What CWhat wants to do is very practical, and call the work in a targeted manner, just like the OS tells VGA to draw me a pie.
It doesn’t make sense if the OS calls "painting pie" to the sound card, memory, and network card, because although the VGA sound card and the memory are all "devices", they
In terms of the realized functions, there is no commonality. This is what I have always said "This situation determines that an interface like IDeviceFace cannot be extracted for all devices, and it cannot be realized!"

Hehe, I am not born in C, but the actual work is a bit hardware inclined.
Reply

Use magic Report

0

Threads

70

Posts

42.00

Credits

Newbie

Rank: 1

Credits
42.00

 China

Post time: 2020-12-15 15:00:01
| Show all posts
For single or not, as you said, it depends on the specific implementation, this is not important in your solution.

Let’s talk about the problem of IDevice. We can’t get a very beautiful IDevice just because we call it "device".
This is ideal. What CWhat wants to do is very practical, and call the work in a targeted manner, just like the OS tells VGA to draw me a pie.
It doesn't make sense for the OS to call "paint pie" to the sound card, to the memory, and to the network card, because although the VGA sound card memory is a "device", from the perspective of the functions they implement, there is no commonality.

I think if you use an object-oriented perspective to consider the relationship between the operating system and the device, I think it should be like this (of course the operating system is implemented in C and assembly, here is just an object-oriented perspective to explain my ideas That's it)

IDevice
{
public
    virtual void in(...) = 0;
    virtual void out(...) = 0;
    virtual char * get_device_name() = 0;
}

class ISoundDevice
{
public:
   virtual void play(...) = 0;
   virtual void setVolume(...) = 0;
   ...
}

class IVideoDevice
{
public:
    virtual draw(...) = 0;
    virtual set_brightness(...) = 0;
    ....
}
Reply

Use magic Report

0

Threads

70

Posts

42.00

Credits

Newbie

Rank: 1

Credits
42.00

 China

Post time: 2020-12-17 18:15:01
| Show all posts
Wrong ISoundDevice and IVideoDevice above need to be derived from IDevice
Reply

Use magic Report

0

Threads

70

Posts

42.00

Credits

Newbie

Rank: 1

Credits
42.00

 China

Post time: 2020-12-17 22:15:01
| Show all posts
You have to worry about synchronization. Too many devices have their own threads, and if they all call back to CWhat, synchronization.. For a single piece
In terms of not only locking synchronization in the construction and destructuring, but also considering more complicated synchronization problems in OnDeviceInterrupt(void*): You can't lock it all at once, so that more than 10 threads are waiting in line during concurrency, which is too inefficient. , Can't do this.

************************************************** ************
Hehe, me too, please correct me if you make a mistake

If you only use one CWhat in the system, no matter what you do, you will face synchronization problems.
If each device uses a separate CWhat, then there is no problem as you said. Isn't it enough to derive IDeviceX from CWhat?
Reply

Use magic Report

2

Threads

13

Posts

12.00

Credits

Newbie

Rank: 1

Credits
12.00

 China

 Author| Post time: 2020-12-17 22:30:02
| Show all posts
to:sky_hexia
I don't know what you mean is correct, is it like this:
========== ========= ======== ========
| CDevice1 | | CDevice2| |CDevice3| ... |CDeviceN|
========== ========= ======== ========
      ↑ ↑ ↑ ↑
      ↓ ↓ ↓ ↓
  Dev1Ctrler Dev2Ctrler ... ...
      ↑ ↑ ↑ ↑
      ↓ ↓ ↓ ↓
================================================= =====
| CWhat? |
================================================= ====
If so, when CDevice1 calls back CWhat, the latter can entrust Dev1Ctrler to do the aftermath, but Dev1Ctrler still
Write the processed status into CWhat, if you directly transfer pWhat to write, then Dev1Ctrler Dev2Ctrler...
It is still tightly coupled with CWhat; if an interface is indirectly adjusted: such as IRecvState (class CWhat:public IRecvStates)
Hmm... it works; when CWhat calls back CDevice1, Dev1Ctrer completes the operation and writes the processing result back
Inside CWhat.
Haha, I feel that CWhat calls CDevice1, CDevice2... is simple, but the whole architecture is too bloated, consider...
Reply

Use magic Report

2

Threads

13

Posts

12.00

Credits

Newbie

Rank: 1

Credits
12.00

 China

 Author| Post time: 2020-12-18 14:15:02
| Show all posts
to:爱德华德
Haha, dude is funny enough.
As far as the level of abstraction is concerned, my opinion is that it is good enough, not too much, too much.
The essence of abstraction is commonality. As long as there is enough commonality, one layer can be extracted.
But there is often a misunderstanding about abstraction, regardless of the actual operation of the system, but doing abstract work with consciousness,
The level of pumping like this is often not high, but low.

Hehe, I also came here. The system often requires trade-offs, how to make it loose, how to make it concise, how to make it efficient,
How to balance between the three is truly optimal for the system. In some key systems, it is often necessary to carefully consider.
Reply

Use magic Report

You have to log in before you can reply Login | Register

Points Rules

Contact us|Archive|Mobile|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

Quick Reply To Top Return to the list