I have a struct like
struct my_struct {
struct list_head queues[NB_QUEUES];
};
I would like to access at the first element of one of the queue (index is computed but I take 2 for the example, which is < NB_QUEUES) like the following (which works without arrays)
struct list_head t = list_first_entry(&foo->queues[2], struct my_struct, ???);
What am I supposed to do to obtain the first element of the queue at the index 2 ? I didn't find anything which compils
So, your code isn't very clear. Let's talk about a more generic example:
I have NB_QUEUES queues. I'm just going to store these as a global variable:
struct list_head queues[NB_QUEUES];
We'll want to make sure that our lists are initialized. We can do that statically with LIST_HEAD_INIT, or at runtime with INIT_LIST_HEAD.
int i;
for (i=0; i<NB_QUEUES; ++i)
INIT_LIST_HEAD(&queues[i]);
We can then push an object of type element into one of these queues:
struct element {
struct list_head list;
int data;
float more_data;
};
struct element *v = kmalloc(sizeof(*v), GFP_KERNEL);
v->data = 4;
v->more_data = 7.2;
list_add(&v.list, &queues[2]);
Later, we can then access the first element in the list.
struct element *q = list_first_entry(&queues[2], struct element, list);
The list argument is from the name of the member of struct element that we used when we inserted this object into the linked list.
Related
For example, I cannot write this:
class A
{
vector<int> v(12, 1);
};
I can only write this:
class A
{
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
};
Why is there a difference between these two declaration syntaxes?
The rationale behind this choice is explicitly mentioned in the related proposal for non static data member initializers :
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):
int x();
struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};
struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:
struct S {
int i(x); // data member with initializer
// ...
static int x;
};
struct T {
int i(x); // member function declaration
// ...
typedef int x;
};
One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:
struct S {
int i(j); // ill-formed...parsed as a member function,
// type j looked up but not found
// ...
static int j;
};
A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:
struct S {
int i(x); // unabmiguously a data member
int j(typename y); // unabmiguously a member function
};
Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).
The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:
HashingFunction hash_algorithm{"MD5"};
Here, we could not use the = form because HasningFunction’s constructor is explicit.
In especially tricky cases, a type might have to be mentioned twice. Consider:
vector<int> x = 3; // error: the constructor taking an int is explicit
vector<int> x(3); // three elements default-initialized
vector<int> x{3}; // one element with the value 3
In that case, we have to chose between the two alternatives by using the appropriate notation:
vector<int> x = vector<int>(3); // rather than vector<int> x(3);
vector<int> x{3}; // one element with the value 3
Problem 2:
Another issue is that, because we propose no change to the rules for initializing static data members, adding the static keyword could make a well-formed initializer ill-formed:
struct S {
const int i = f(); // well-formed with forward lookup
static const int j = f(); // always ill-formed for statics
// ...
constexpr static int f() { return 0; }
};
Problem 3:
A third issue is that class-scope lookup could turn a compile-time error into a run-time error:
struct S {
int i = j; // ill-formed without forward lookup, undefined behavior with
int j = 3;
};
(Unless caught by the compiler, i might be intialized with the undefined value of j.)
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms.
We believe:
Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.
Problem 2: adding the static keyword makes a number of differences, this being the least of them.
Problem 3: this is not a new problem, but is the same order-of-initialization problem that already exists with constructor initializers.
One possible reason is that allowing parentheses would lead us back to the most vexing parse in no time. Consider the two types below:
struct foo {};
struct bar
{
bar(foo const&) {}
};
Now, you have a data member of type bar that you want to initialize, so you define it as
struct A
{
bar B(foo());
};
But what you've done above is declare a function named B that returns a bar object by value, and takes a single argument that's a function having the signature foo() (returns a foo and doesn't take any arguments).
Judging by the number and frequency of questions asked on StackOverflow that deal with this issue, this is something most C++ programmers find surprising and unintuitive. Adding the new brace-or-equal-initializer syntax was a chance to avoid this ambiguity and start with a clean slate, which is likely the reason the C++ committee chose to do so.
bar B{foo{}};
bar B = foo();
Both lines above declare an object named B of type bar, as expected.
Aside from the guesswork above, I'd like to point out that you're doing two vastly different things in your example above.
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
The first line initializes v1 to a vector that contains two elements, 12 and 1. The second creates a vector v2 that contains 12 elements, each initialized to 1.
Be careful of this rule - if a type defines a constructor that takes an initializer_list<T>, then that constructor is always considered first when the initializer for the type is a braced-init-list. The other constructors will be considered only if the one taking the initializer_list is not viable.
So I wanted to practice my skills of using smart pointers. I created a template of class (one-linked list) that has constructor like:
template <class Type>
class list
{
//...
public:
list( std::initializer_list < Type > initlist ) { ... }
//...
};
In main-function I want to construct initializer list and pass it to the class constructor as one thing (smth like this, I think it can be possible but I don't know how to do):
typedef int Type;
int main ()
{
//...
size_t count; // to know How many elements initlist will have
std :: initializer_list < Type > initlist;
cout << "Enter, please, count of elements and their values\n";
cin >> count;
Type temp_data;
for (size_t i = 0; i < count; i++)
{
cin >> temp_data; //user input data and program add it to list
initlist.push_back( temp_data );
// it's wrong. But I found no analogue of "push_back" in std :: initializer_list
// I used push_back to explain what I want to do
}
// ... do stuff
// now I want to pass it to the class object
list < Type > mylist ( initlist ); // or mylist = initlist, or mylist{initlist}
}
I could do smth like below but if I don't know how many and what elements will be input by user then what I should do:
list <Type> mylist {1,2,3,4,5,6,7,8};
So, What should I do to write it correctly? Maybe somebody has an idea.
Thanks.
Usually in C++ containers provide both an std::initializer_list constructor and a constructor that takes two iterators (of any given size) and copies the content of that "range" into the container.
So for example your class could have something like this:
template <class Type>
class list {
//...
public:
list(std::initializer_list<Type> initlist) { ... }
template<typename It>
list(It begin, It end) { ... }
//...
};
In the standard library std::vector, std::list, std::forward_list, std::deque and other containers all support those.
This is done so that if a user knows the elements he/she wants to insert into the container at the moment the container is created he/she uses the std::initializer_list overload. Otherwise if he/she has some other dynamically built container, he can just import the elements in your container.
There is no such thing as a dynamically-sized std::initializer_list. That class is supposed to be lightweight and simple.
You could instead implement push_back or push_front for your list class and build it up incrementally.
The analogue to your current idea would be to build up a std::vector or similar, then provide a constructor which takes an iterator range to copy from that container.
I have been studying I2C driver (client) code for a while.
I have seen this function "i2c_get_clientdata" and "i2c_set_clientdata" every where.
I have seen the this question here .
Use of pointer to structure instead of creating static local copy
Some times i think like it is like "container_of" macro to get a pointer to the structure.
But still i didn't understood properly why to use it and when to use it.
Below i am posting a sample code where I see its usage.
If any one could help me understand why it is used there and when we shall use it when we write our own drivers.
struct max6875_data {
struct i2c_client *fake_client;
struct mutex update_lock;
u32 valid;
u8 data[USER_EEPROM_SIZE];
unsigned long last_updated[USER_EEPROM_SLICES];
};
static ssize_t max6875_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
int slice, max_slice;
if (off > USER_EEPROM_SIZE)
return 0;
if (off + count > USER_EEPROM_SIZE)
count = USER_EEPROM_SIZE - off;
/* refresh slices which contain requested bytes */
max_slice = (off + count - 1) >> SLICE_BITS;
for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
max6875_update_slice(client, slice);
memcpy(buf, &data->data[off], count);
return count;
}
Those functions are used to get/set the void *driver_data pointer that is part of the struct device, itself part of struct i2c_client.
This is a void pointer that is for the driver to use. One would use this pointer mainly to pass driver related data around.
That is what is happening in your example. The max6875_read is a callback getting a structu kobject. That kobject is an i2c_client which is enough to communicate with the underlying device using the driver_data pointer here allows to get back the driver related data (instead of using global variables for example).
I've a problem with boost intrusive containers.
One of my classes has an intrusive list of some objects, whose lifetimes are strictly managed by it. The objects themselves are meant to be modified by the users of the class, but they are not supposed to modify the list itself. That's why I'm only providing access to the list through a "getList" function, which returns a const version of the intrusive list.
The problem with const intrusive lists is that the elements also turn out to be const when you're trying to iterate through them. But the users should be able to iterate through and modify the items.
I don't want to keep a separate list of pointers to give to the users, because that would invalidate one of the biggest advantages of using intrusive containers. Namely, the ability to remove items from the container in constant time, while the only thing you have is a pointer to the item.
It would be sad to have to give a non-const version of my list just because of a limitation of C++. So the question is: Is there a special const version of the boost intrusive containers, which magically allows item modifications while disallowing any modifications on the list itself?
You don't need to return a list, give an access to separate items by reference
OK, I've designed a complete solution to the problem. Andy's solution is nice, if you don't need to iterate over the items in an efficient manner. But I wanted something that's semantically equivalent to const std::list. Maybe it's an overkill, but performance wise there's almost no difference after optimizations:
The solution is to privately extend the intrusive list with a class called ConstList, which exposes just enough to let BOOST_FOREACH iterate, but not to make any changes by anyone. I've moved the list hook from the item to a child class, so that an item object cannot be used to change the list either. We're storing the child class with the hook, but our iterators are returning references to the item class. I've coded this solution into two templated classes for easy application to any item class.
I've made a header file with the ConstList class and the HookedItem class, followed by the tests.cpp, used to test and benchmark. You'll see that our ConstList class has equal performance while iterating.
It works quite cleanly, and the user code also stays clean. Then this begs the question: Why isn't this already in boost????!?!?
Feel free to use the following code for any purpose :)
P.S: I've had a moment of revelation while coming up with this solution: "const" is nothing but a syntactic sugar for a special case of what you can already achieve with the right class hierarchy. Is that true, or was I over-generalizing?
------------------ ConstList.h -----------------------
#include <boost/intrusive/list_hook.hpp>
template < typename T>
struct type_wrapper{ typedef T type;};
template<class listType, class owner, class item>
class ConstList: private listType {
friend class type_wrapper<owner>::type;
public:
class iterator {
typename listType::iterator it;
public:
typedef std::forward_iterator_tag iterator_category;
typedef item value_type;
typedef int difference_type;
typedef item* pointer;
typedef item& reference;
template<class T>
iterator(const T it): it(it){}
bool operator==(iterator & otherIt) {return it==otherIt.it;}
iterator & operator++() {
it++;
return *this;
}
item & operator*() {
return *it;
}
};
iterator begin() {
return iterator(listType::begin());
}
iterator end() {
return iterator(listType::end());
}
};
template<class item, class owner, class hooktype>
class HookedItem: public item {
friend class type_wrapper<owner>::type;
public:
hooktype hook_;
typedef boost::intrusive::member_hook<HookedItem, hooktype, &HookedItem::hook_> MemberHookOption;
private:
template<class Arg1, class Arg2>
HookedItem(Arg1 &arg1, Arg2 &arg2): item(arg1, arg2){}
};
------------------ tests.cpp -----------------------
#include<cstdio>
#include<boost/checked_delete.hpp>
#include<ConstList.h>
#include<boost/intrusive/list.hpp>
#include<boost/foreach.hpp>
using namespace boost::intrusive;
class myOwner;
class myItem {
public:
int a,b; //arbitrary members
myItem(int a, int b): a(a), b(b){};
};
typedef HookedItem<myItem,myOwner,list_member_hook<> > myHookedItem;
typedef list<myHookedItem, typename myHookedItem::MemberHookOption> myItemList;
typedef ConstList<myItemList,myOwner,myItem> constItemList;
class myOwner {
public:
constItemList constList;
myItemList & nonConstList;
myOwner(): nonConstList(constList) {}
constItemList & getItems() { return constList;}
myItem * generateItem(int a, int b) {
myHookedItem * newItem = new myHookedItem(a,b);
nonConstList.push_back(*newItem);
return newItem;
}
~myOwner() {nonConstList.clear_and_dispose(boost::checked_delete<myHookedItem>);}
};
int main(int argc, char **argv) {
myOwner owner;
int avoidOptimization=0;
for(int i=0; i<1000000; i++) {
owner.generateItem(i,i);
}
clock_t start = clock();
for(int i=0; i<1000; i++)
BOOST_FOREACH(myItem & item, owner.constList)
avoidOptimization+=item.a;
printf ( "%f\n", ( (double)clock() - start ) / CLOCKS_PER_SEC );
start = clock();
for(int i=0; i<1000; i++)
BOOST_FOREACH(myHookedItem & item, owner.nonConstList)
avoidOptimization+=item.a;
printf ( "%f\n", ( (double)clock() - start ) / CLOCKS_PER_SEC );
printf ("%d",avoidOptimization);
return 0;
}
------------ Console Output -----------------
4.690000
4.700000
1764472320
I'm taking my first crack at writing some linux kernel code, and I'm hitting a weird kernel panic.
I have a linked list I am maintaining with the kernel's built-in macros (include/linux/list.h). If the list is empty, I allocate an instance of the following structure:
struct time_span
{
struct timeval start;
struct timeval end;
};
and point to it with a pointer called "tmp". I add tmp to the list I'm maintaining with list_add_tail().
Later, if the list is not empty (I'm trying to test with one list item to simplify debugging), I point to the first item in the list with tmp and try to print out the contents of tmp->end.tv_sec. Unfortunately, this causes a kernel panic.
tmp is not NULL (I check at run-time) and neither is "tmp->end" (I am able to print both). It's only when I try to access one of the fields in "end" that I get a kernel panic. I've never seen something like this before -- does anyone have any ideas?
Thanks for any assistance!
-------EDIT------
Code example (this lives in a function that will be called repeatedly):
// .........
struct timeval now_tv;
do_gettimeofday(&now_tv);
if(!list_empty(&(my_list.time_list)))
{
tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list);
if(tmp != NULL)
{
tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS
// Attempting to print "tmp->end.tv_sec" also breaks.
tmp->end.tv_usec = now_tv.tv_usec;
}
}
// .........
if(list_empty(&(my_list.time_list)))
{
new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL);
INIT_LIST_HEAD(&(new_time_span->time_list));
list_add_tail(&(new_time_span->time_list), &(my_list.time_list));
do_gettimeofday(&(new_time_span->start));
}
// ........
You're missing some fundamentals about Linux linked lists.
The following should change:
struct time_span
{
struct timeval start;
struct timeval end;
};
To:
struct time_span
{
struct timeval start;
struct timeval end;
struct list_head time_list;
}
When using Linux linked lists you should put the struct list_head inside your struct that you want a list of.
In the code below, you're allocating a type struct time_span and referencing a variable named time_list inside the allocated variable new_time_span... but you haven't added that to your struct above.
// .........
struct timeval now_tv;
do_gettimeofday(&now_tv);
if(!list_empty(&(my_list.time_list)))
{
tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list);
if(tmp != NULL)
{
tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS
// Attempting to print "tmp->end.tv_sec" also breaks.
tmp->end.tv_usec = now_tv.tv_usec;
}
}
Based on the information you've provided, I don't know why the above breaks. Maybe it's just that tmp is a pointer pointing to garbage and that's why it crashes? If you have a kernel debugger setup it's easy to verify.
// .........
if(list_empty(&(my_list.time_list)))
{
new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL);
INIT_LIST_HEAD(&(new_time_span->time_list));
list_add_tail(&(new_time_span->time_list), &(my_list.time_list));
do_gettimeofday(&(new_time_span->start));
}
// ........
Here are some good articles that should help:
http://kernelnewbies.org/FAQ/LinkedLists
http://sumanadak.blogspot.com/2006/09/linux-kernel-linked-list.html