I am reading datastructures and see stack and queue but i do not get enough examples in computer systems or web development or specific problems where i should use a stack or queue or a tree etc.
Stacks are used by most (all?) programming languages to keep track of the state of the program when sub-routines are called.
Explanation: The code of your program is stored in main memory. The CPU has an instruction pointer that always points to the next instruction that will be executed. When an instruction has been executed, this pointer is increased by one, to point to the next instruction.
When your program enters a sub-routine, the instruction pointer jumps to some other address. When that routine is finished, it has to know where it left of. So, the last address before the jump is pushed on the stack. When the function is finished, the topmost item on the stack will be that address.
This is also the reason why excessive recursion can lead to a stack-overflow. Too many nested calls lead to many return addresses being pushed on the stack, but none are removed.
Read more on Wikipedia.
Trees can be used for many things, for instance binary search trees.
Queues are common whereever something needs to be handled on a first-come-first-serve principle. Network packets, I/O requests, etc.
You want a stack when you need to re-use the last item you put on it again. I can't find a nice example off the top of my hat, but it's used e.g. in converting normal mathematical expressions into RPN or for storing nodes when doing a depth-first search in a graph.
Queue - First In First Out, used for sequntial processing of data. Can be used for processing tasks in the order they were enqueued.
Stack is the opposite of the Queue - Last In First Out, most commonly used example - method call stack.
In stack deletion and insertion are performed on the same end. So it is called Last In First Out. In stack only one pointer is used called TOP.No wastage of memory space
In queue deletion and insertion are performed on two ends. So, it is called First In First Out. In queue two pointer called as FRONT and REAR.Wastage of memory space.
Related
Circular queue is obviously better because it helps us to use the empty space left by popping out the elements. It also saves time that may have been used to do lateral shift of elements after each pop.
But is there any use case where queue would be preferred than using a circular queue?
Definition of Queue = We will go with the linear array implementation. Follows FIFO and no overwrites
Definition of Circular Queue = Ring Buffer Implementation. Follows FIFO. No overwrites.
Note: In many languages a queue is just an interface and doesn't say anything about the implementation.
When using an array based circular queue, a.k.a ring buffer, you must handle the situation where you push to a full buffer. You could:
Ignore the insertion
Overwrite the oldest entry
Block until there's space again
(Re)Allocate memory and copy all the content
Use an oversized buffer so this situation never happens
Each of these options have downsides. If you can live with them or you know that you will never fill the buffer, then ring buffer is the way to go.
Options 3 & 4 will induce stuttering. Depending on your use case, you might prefer longer but stable access time and reliability over occasional spikes and therefore opt for a linked list or some other sort of dynamic implementation, like a deque, instead.
Example use cases are tasks, where you have to achieve a stable frame/sampling rate or throughput and you can't tolerate stutters, like:
Realtime video and audio processing
Realtime rendering
Networking
Thread pools when you don't want the threads to block for too long when pushing new jobs.
However, a queue based on a linear array will suffer from the same downsides. I don't see a reason for choosing a linear queue over a circular queue.
(Besides the slightly higher implementation complexity.)
std::queue in C++ uses a deque as underlaying container by default. deque is essentially a dynamic array of arrays which seems like a good base for most use cases because it allocates memory in small chunks and hence induces less stuttering.
It seems true, but my thought has been muddy.
can someone give a clear explanation and some crucial cases in which it always works without locking? thanks!
The real trick behind the single producer - single consumer circular queue is that the head and tail pointers are modified atomically. This means that if a position in memory is changed from value A to value B, an observer (i.e. reader) that reads the memory while its value is changed will get either A or B as a result, nothing else.
So your queue will not work if, for example, you are using 16-bit pointers but you are changing them in two 8-bit steps (this may happen depending on your CPU architecture and memory alignment requirements). The reader in this case may read an entirely wrong transient value.
So make sure that your pointers are modified atomically in your platform!
This surely depends on the implementation of the cyclic queue. However, if it is as I imagine it you have two indices - the head and the tail of the queue. The producer works with the tail and the consumer works with the head. They share the message array, but use two different pointers.
The only case in which the producer and the consumer might run into conflict is the one in which e.g. the consumer checks for new message and it arrives just after the check. However in such case the consumer will wait a bit and check once more. The correctness of the program will not be lost.
The reason why it works ok with single producer single consumer is mainly because the two users do not share much of memory. In case of multiple producers e.g. you will have more than a single thread accessing the head and conflicts might arraise.
EDIT as dasblinkenlight mentions in his comment my reasoning holds true only if both threads increment/ decrement their respective counters as last operation of their consuming/producing.
in clone (2) man page, for child stack its mentioned that
Since the child and calling process may share memory, it is not possible for the child
process to execute in the same stack as the calling process.
can anybody please explain how "sharing memory" ,specifically, makes it impossible. OTOH, a common perception is that the function execution sequence in a thread will be different from others, so we need another stack there.
Thanks,
Kapil
Two threads can't use the same stack. They'd just mess it up for each other, and soon crash.
When using fork, there's no memory sharing. Both threads have the same value of the stack pointer, but it points to physically different memory pages.
When using pthread_create, a new stack pointer is chosen for the new thread, separate from the parent. This way they don't corrupt each other's stack.
clone is a low-level function, which is somewhere between the two. It keeps memory shared, so the threads must not shared the stack. But unlike pthread_create, the new stack pointer is determined by the user, which may choose it as he wishes. The sentence you quote warns that you should choose it with care.
Are return address and data mixed/stored in the same stack, or in 2 different stacks, which is the case?
They are mixed. However, it depends on the actual programming language / compiler. I can image a compiler allocating space for local variable on the heap and keeping a pointer to the storage on the stack.
There is one stack per thread in each process. Hence, for example, a process with 20 threads has 20 independent stacks.
As others have already pointed out, it's mostly a single, mixed stack. I'll just add one minor detail: reasonably recent processors also have a small cache of return addresses that's stored in the processor itself, and this stores only return addresses, not other data. It's mostly invisible outside of faster execution though...
It depends on the compiler, but the x86 architecture is geared towards a single stack, due to the way push and pop instructions work with a single stack pointer. The compiler would have to do more work maintaining more than one stack.
On more note: every thread in Win32 has its own stack. So, when you tell "windows program" - it depends on how many threads it has. (Of course threads are created/exited during the runtime).
With reference to Stack Based Memory Allocation, it is stated as "...each thread has a reserved region of memory referred to as its stack. When a function executes, it may add some of its state data to the top of the stack; when the function exits it is responsible for removing that data from the stack" and "...that memory on the stack is automatically, and very efficiently, reclaimed when the function exits"
The first quoted sentence says the current thread is responsible and second quoted sentence says its done automatically.
Question 1: Is it done automatically or by the current running thread?
Question 2: How the deallocation of memory takes place in Stack?
Question 1: by automatically (and very efficiently) they mean that just by shifting a memory pointer around (cutting the top off the stack), all memory used there is reclaimed. There is no complex garbage collection necessary.
Question 2: the stack is just a contiguous chunk of memory delimited by a start and an end pointer. Everything between the pointers belongs to the stack, everything beyond the end pointer is considered free memory. You allocate and deallocate memory by moving the end pointer (the top of the stack) around. Things are much more complicated on the heap, where memory use is fragmented.
You might understand more by looking at an example of a Call Stack (such as in C on many machines).
Question 1: Yes.
Question 2: by decreasing the stack pointer, i.e. the reverse operation of allocation.
The stack is managed by the compiler.
The heap is managed by a library.
ans to the question 1: yes its automatically done by the garbage collector as it is daemon process running always with the jvm. it checks for all the references and if they dont have references(or out of reach) then it will remove it from the heap.
ans to the question 2: as the local variables and method calls will be stored in stack as soon as they will be out of scope they will be removed from the stack.