GCD dispatch_set_target_queue function's 1st parameter type - multithreading

The function prototype is this:
void dispatch_set_target_queue(
dispatch_object_t object,
dispatch_queue_t queue);
typedef union {
struct dispatch_object_s *_do;
struct dispatch_continuation_s *_dc;
struct dispatch_queue_s *_dq;
struct dispatch_queue_attr_s *_dqa;
struct dispatch_group_s *_dg;
struct dispatch_source_s *_ds;
struct dispatch_source_attr_s *_dsa;
struct dispatch_semaphore_s *_dsema;
struct dispatch_data_s *_ddata;
struct dispatch_io_s *_dchannel;
struct dispatch_operation_s *_doperation;
struct dispatch_fld_s *_dfld;
} dispatch_object_t __attribute__((transparent_union));
I am confused why below code could pass compiling???
dispatch_queue_t queueA = dispatch_queue_create("com.effectiveobjectivec.queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("com.effectiveobjectivec.queueB", NULL);
dispatch_set_target_queue(queueB, queueA); // will set queueA as queueB's target
I don't see any field in dispatch_object_t Union is a dispatch_queue_t, so how can queueB argument cause no compile errors?
Also. I wonder what "struct dispatch_object_s *_do;" field is? What is "struct dispatch_queue_s *_dq;"?

You can think of dispatch_object_t as the "base class" of all the dispatch object types.
In "plain" C this uses the transparent union GCC extension, which essentially allows all pointer types in the union to be treated interchangeably with the union type when used as a function argument.
the macro below the block you quoted from dispatch/object.h explains the connection with dispatch_queue_t:
#define DISPATCH_DECL(name) typedef struct name##_s *name##_t
and then later on in dispatch/queue.h
DISPATCH_DECL(dispatch_queue);
i.e. dispatch_queue_t matches the _dq member of the transparent union and hence is a valid type to pass to the dispatch_object_t argument of dispatch_set_target_queue.
FWIW in Objective-C and C++ the dispatch_object_t superclass relationship is expressed using the respective object type system, c.f. the other sections in the dispatch_object_t area of dispatch/object.h.

Related

What is the difference between these two types of data struct?

Can anyone tell me what the difference between these two types of data structures is? The first one uses TAG "worker". In the second one I declared the names in the data structure itself "rober" and "zzymon". As for me, the first one is more practical to use...
// FIRST structure TAG**
struct worker
{
int age1;
char *hair_color1;
};
struct worker grzegorz;
grzegorz.age1 = 15;
grzegorz.hair_color1 = "gray";
struct worker krzys;
krzys.age1 = 26;
krzys.hair_color1 = "white";
// SECOND structure variables struct type**
struct
{
int age2;
char *hair_color2;
}
robert, szymon;
robert.age2 = 12;
robert.hair_color2 = "blond";
szymon.age2 = 14;
szymon.hair_color2 = "gray";
The first one defines a struct type struct worker and then later defines two instances of that struct type grzgorz and krzys.
The second one defines two instances of an anonymous struct type called robert and szymon
In both cases, you get two objects of the same struct type you can do things with. In the first case, that struct type also has a name, so you can later define other things with the same type (or pointers to that type, etc), while in the second case you cannot, as the struct type is anonymous.

Why doesn't the struct update syntax work on non-exhaustive structs?

In the struct update syntax, the "spreaded" struct must be the same type as the resulting struct. So the spreaded struct has to contain all fields already.
What, then, is left that is not "exhausted"? Why is the struct update syntax not allowed for non-exhaustive struct?
use some_crate::NonExhaustiveStruct;
let a = NonExhaustiveStruct::default();
let b = {
some_field: true,
..a //Why doesn't this work?
};
This is currently an explicitly unsupported edge case: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html#functional-record-updates. Within the same crate struct spread update syntax is allowed on non-exhausive structs but it is not allowed when the struct is defined in a separate crate.
The reasoning for this is that a private field could be added in future, and code outside the crate can't do spread updates of structs with private fields.

What are the differences between the multiple ways to create zero-sized structs?

I found four different ways to create a struct with no data:
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
struct C(()); // unit-valued tuple struct
struct D; // unit struct
(I'm leaving arbitrarily nested tuples that contain only ()s and single-variant enum declarations out of the question, as I understand why those shouldn't be used).
What are the differences between these four declarations? Would I use them for specific purposes, or are they interchangeable?
The book and the reference were surprisingly unhelpful. I did find this accepted RFC (clarified_adt_kinds) which goes into the differences a bit, namely that the unit struct also declares a constant value D and that the tuple structs also declare constructors B() and C(_: ()). However it doesn't offer a design guideline on why to use which.
My guess would be that when I export them with pub, there are differences in which kinds can actually be constructed outside of my module, but I found no conclusive documentation about that.
There are only two functional differences between these four definitions (and a fifth possibility I'll mention in a minute):
Syntax (the most obvious). mcarton's answer goes into more detail.
When the struct is marked pub, whether its constructor (also called struct literal syntax) is usable outside the module it's defined in.
The only one of your examples that is not directly constructible from outside the current module is C. If you try to do this, you will get an error:
mod stuff {
pub struct C(());
}
let _c = stuff::C(()); // error[E0603]: tuple struct `C` is private
This happens because the field is not marked pub; if you declare C as pub struct C(pub ()), the error goes away.
There's another possibility you didn't mention that gives a marginally more descriptive error message: a normal struct, with a zero-sized non-pub member.
mod stuff {
pub struct E {
_dummy: (),
}
}
let _e = stuff::E { _dummy: () }; // error[E0451]: field `_dummy` of struct `main::stuff::E` is private
(Again, you can make the _dummy field available outside of the module by declaring it with pub.)
Since E's constructor is only usable inside the stuff module, stuff has exclusive control over when and how values of E are created. Many structs in the standard library take advantage of this, like Box (to take an obvious example). Zero-sized types work in exactly the same way; in fact, from outside the module it's defined in, the only way you would know that an opaque type is zero-sized is by calling mem::size_of.
See also
What is an idiomatic way to create a zero-sized struct that can't be instantiated outside its crate?
Why define a struct with single private field of unit type?
struct D; // unit struct
This is the usual way for people to write a zero-sized struct.
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
These are just special cases of basic struct and tuple struct which happen to have no parameters. RFC 1506 explains the rational to allow those (they didn't used to):
Permit tuple structs and tuple variants with 0 fields. This restriction is artificial and can be lifted trivially. Macro writers dealing with tuple structs/variants will be happy to get rid of this one special case.
As such, they could easily be generated by macros, but people will rarely write those on their own.
struct C(()); // unit-valued tuple struct
This is another special case of tuple struct. In Rust, () is a type just like any other type, so struct C(()); isn't much different from struct E(u32);. While the type itself isn't very useful, forbidding it would make yet another special case that would need to be handled in macros or generics (struct F<T>(T) can of course be instantiated as F<()>).
Note that there are many other ways to have empty types in Rust. Eg. it is possible to have a function return Result<(), !> to indicate that it doesn't produce a value, and cannot fail. While you might think that returning () in that case would be better, you might have to do that if you implement a trait that dictates you to return Result<T, E> but lets you choose T = () and E = !.

How does a repr(C) type handle Option?

I have this C code:
typedef void (*f_t)(int a);
struct Foo {
f_t f;
};
extern void f(struct Foo *);
bindgen generates the following Rust code (I have removed unimportant details):
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct Foo {
pub f: ::std::option::Option<extern "C" fn(a: ::std::os::raw::c_int)>,
}
I do not understand why Option is here. Obviously that Rust enum and C pointer are not the same thing on the bit level, so how does the Rust compiler handle this?
When I call the C f function and pass a pointer to a Rust struct Foo, does the compiler convert Foo_rust to Foo_C and then only pass a pointer to Foo_C to f?
From The Rust Programming Language chapter on FFI (emphasis mine):
Certain types are defined to not be null. This includes references (&T, &mut T), boxes (Box<T>), and function pointers (extern "abi" fn()). When interfacing with C, pointers that might be null are often used. As a special case, a generic enum that contains exactly two variants, one of which contains no data and the other containing a single field, is eligible for the "nullable pointer optimization". When such an enum is instantiated with one of the non-nullable types, it is represented as a single pointer, and the non-data variant is represented as the null pointer. So Option<extern "C" fn(c_int) -> c_int> is how one represents a nullable function pointer using the C ABI.
Said another way:
Obviously that Rust enum and C pointer are not the same thing on the bit level
They actually are, when the Option contains a specific set of types.
See also:
Can I use the "null pointer optimization" for my own non-pointer types?
What is the overhead of Rust's Option type?
How to check if function pointer passed from C is non-NULL

Malloc a struct within a struct?

I decided to use structs in this program to keep it organized so I now have a chain of structs. My question is if I must malloc a struct that is within another struct. For example:
typedef struct OnlineS {
struct BBSIS *bbsi;
struct BBVIS *bbvi;
struct VBVIS *vbvi;
} *OnlineP;
typedef struct BBSIS{
struct FirstFitS *ff;
struct BestFitS *bf;
struct NextFitS *nf;
int itemNum;
int binNum;
int binMin;
int binMax;
int *items;
}*BBSIP;
And so on, so would my declaration and mallocs look like?
OnlineP on = malloc(sizeof (struct OnlineS));
on->bbsi = malloc(sizeof (struct BBSIS));
on->bbsi->bf = malloc(sizeof (struct BestFitS));
on->bbsi->nf = malloc(sizeof (struct NextFitS));
on->bbsi->ff = malloc(sizeof (struct FirstFitS));
on->bbvi = malloc(sizeof (struct BBVIS));
on->bbvi->bf = malloc(sizeof (struct BestFitS));
//ETC
If you use pointers to structs within a struct you must manage memory for that as well. (malloc/free)
If tou use structs within a struct you do not manage memory for the internal structures. Since they are part of the outer struct there is no need to.
You use pointer to structs in your outer struc so you must use malloc and free.
First allocate memory for your outer struct, then set all pointers to the inner structs to null or allocate memory for it.
There is no struct in your struct.
There is a pointer in your struct, and the memory for the pointer was allocated.
Consider the following construct:
typedef struct node {
struct node* next;
}
(Which is very common - a linked list)
How many nodes should it allocate?

Resources