I'm trying to use the list utility that is recommended in Linux kernel.
From the introduction in https://isis.poly.edu/kulesh/stuff/src/klist/ one of the feature of the list_head is that the element can belongs to different lists.
Now, if I want a list of all the staff and a list of the old staff only, I think I have to define the following data and structure:
struct list_head all_staff;
struct list_head old_staff;
struct staff {
int age;
struct list_head list; // for all the staff;
struct list_head old;
};
On the other hand, the normal list implementation may be like this:
struct staff {
int age;
};
struct node {
struct node *prev;
struct node *next;
void *element;
};
What's the advantage of list_head compare to the normal list implementation? I feel although the list_head only includes 2 points, removes the point to the element, and so it saves memory, but in this case, I have to add another list_head in the staff structure, if there is only 1 old staff, then it will waste lots of memory.
What's more, if the staff belongs to many different groups, does it mean I have to add many list_head in the staff structure?
Thanks.
if the staff belongs to many different groups, does it mean I have to add many
list_head in the staff structure?
Yes, you need several list_head fields in the stuff object so it can belong to several lists at the same time.
What's the advantage of list_head compare to the normal list implementation?
list_head is ready-made implementation. But when use "normal" lists, you need to implement list functions manually for every object type you use as a list element.
Related
I kinda newbee and have an architecture problem on go & interface:
I need to store info about Vehicle and assume it could be Car, Bus, Ambulance, Firetruck etc. So Vehicle is interface and every exact Vehicle type is struct, but all of them have some common fields (colour, number of wheels, seats, mufflers etc) and when I need to get something common I can go following ways:
Don't use interface at all and have one big struct with a lot of getters and setters checked every time "if vehicle type X can have field Z?". It makes those methods very hard to read and very easy to forget to check smthng.
Perform type assert every time on every type to get exact field. So just to get colour I will need to write type switch for 10 lines.
Add to interface getter for every common field:
type Vehicle interface {
Colour() string
Wheels() int
Seats() int
Mufflers() int
...
}
As I see it's anti-pattern for "keep interface small" and will produce a lot of very similiar code (same method for every struct)
Have some struct like CommonVehicle which store all common fields and all other vehicle type embed it and interface have only method return this CommonVehicle:
type Vehicle interface {
Common() CommonVehicle
}
type CommonVehicle struct {
// common fields
}
type Car struct {
CommonVehicle
// uncommon fields
}
// implementation for Vehicle interface
When I need to get colour I will do vehicle.Common().Colour. It looks clear on interface and types side, but it could mislead to call every time Common to get anything from Vehicle.
What is the best practice for this? Maybe I missed something and need to go some other way?
You are trying to have Inheritance which is not supported in Go (and some believe it is not a good pattern overall). Instead, you should use Composition (which is exactly what your #4 option suggests).
This blog post describes it perfectly
A different approach as a general design rule
instead of trying to define interfaces of objects, you should aim towards capabilities you wish your objects will be able to do.
This does not correlate 100% with your question but it will help with maintaining the pattern of small interfaces.
Let's take a vehicle as an example: what can we do with a vehicle?
drive it
perhaps listen to music
sell it
be amazed of its beauty
Now that we know what we can do with a vehicle, we should have each of these actions as its own interface.
Why? - because it allows for the most granular description of any vehicle entity, without any assumptions about what specific implementations of a vehicle have.
So we have the following interfaces:
type Drivable interface{ Drive(float64, float64) } // drive to a latitude, longitude quordinate
type Listenable interface{ Listen() []byte } // Listen return a stream of bytes as the audio output
type Sellable interface { Sell(float64, string) } // sell for X amount of money to some person
type Describable interface { Describe() string }
Now with these 4 interfaces, we can create any type of vehicle we want:
Some vehicles won't have a radio, so they probably shouldn't implement the Listenable interface.
Some vehicles are police vehicles - the city owns them - so they are not really sellable
etc, etc...
The point is to have different capabilities and from those capabilities we should build our entities - and not vice-versa.
I have a matrix struct written in Go. That matrix struct has a bunch of methods. I want to be able to efficiently compute matrix operations but I also want to be able to send it over the wire in order to distribute the computation.
I currently have the matrix and its methods separate from the protobuf definition. When I need to send it over the wire I have to create a new pb.Matrix{} from the existing Matrix{} struct and then make my grpc call. That seems like a waste. So, is it a waste? And should I just be defining my matrix struct as a protobuf definition and then use embedding to define operations on it? Or is it better to keep them separate from each other?
In terms of architecture, I'd keep them separate. That would agree with the Single Responsibility Principle. In one of my projects we use this form:
type Foo struct { ... }
func NewFooFromProto(f *myproto.Foo) *Foo { ... }
func (f *Foo) ToProto() *myproto.Foo { ... }
I am working on a driver that creates a sysfs attribute file. It is intended that an application be notified of changes to this attribute by using the poll() method. I intend to use the sysfs_notify() function for this. This is easy to do as long as you have the kobject for the attribute (sysfs_notify() requires that as the first parameter). Getting the kobject is easy enough if using sysfs_create_file() and related functions.
I read this post on correctly creating a sysfs file that solves a possible race condition between userspace notification that the device is present, and the creation of the sysfs files. This solution is also much cleaner.
However, I cannot figure out how to get the kobject for each of the attributes (or parent) that I can use in sysfs_notify(). At one point structures such as struct device_driver had a member of struct kobject kobj;. That was replaced (10ish years ago) with struct driver_private *p;. This private structure now contains the actual kobject and is not available for use.
Is there a new form of sysfs_notify() that I can use, or is there another way of getting the correct kobject? I may have to go back to "manually" creating the sysfs attribute otherwise.
I want the user to pass a pointer to a struct and the system call will assign values to the field in the struct.
Where should I define this struct so that it is accessible to the userspace programs?
I know in C++/CLI one cannot use unmanaged types when defining a managed class:
public struct Unmanaged
{
int x;
int y;
};
public ref class Managed
{
int one;
Unmanaged two; //error C4368
};
I do not understand why though. Unmanaged is simply a collection of native types - its size is known, surely it (and by it I mean the block of memory that defines it) would be moved around with the 'block of memory' that is Managed inside the 'managed heap', and whatever offset is stored in the metadata will remain valid, no? Just as if an integer or a float were declared?
Why can we not mix types?
Mixed type actually refers to the mixed memory models. Unmanaged types go on the heap, managed types go in the garbage collected heap, so when you embed an unmanaged type in a managed, it would require memory on both heaps, which is why you do this sort of thing with a pointer. The pointer is managed, the value it points to isn't.
I was curious myself, so I gathered up my google and found this.
http://blogs.msdn.com/b/branbray/archive/2005/07/20/441099.aspx
Guy seems to know what he's talking about.
Good question though...