JavaScript and Event loop

JavaScript and Event loop

JavaScript is gaining popularity on all stacks whether it is front end or back end development in-spite of single-threaded in nature. Being a hardcore C++ developer, I understand what is a multi-threaded application and how it works, but JavaScript is single-threaded. How people are writing applications with a single-threaded language. 
Single-threaded means one task at one time, how JavaScript is handling multiple tasks in parallel (multiple ajax request and reading a file from filesystem along with the other computations).

When I asked this query to nodeJs developers, I got the standard answer that though Js is single-threaded but it has event-loop that takes care of parallel tasks.
Again, I could not understand the statement at all, I decided to search over the internet and found interesting facts.

Yes, It is an event-loop that does the magic. Let us understand how.
First, understand the call stack for the case below:


    function foo() {
        console.log("I am foo");
    }

    function bar() {
        foo();
        console.log("I am bar");
    }

    function square() {
        bar();
        console.log("I am square");
    }

    square();


All the functions are stored in a stack memory and it's data stored in heap memory. This is the case of blocking functions and it is straight forward to understand.

The output will be like:

I am foo
I am bar
I am square


Let us change the function foo() like below

function foo() {
    setTimeout(() => {
        console.log("I am foo");
    }, 5000);
}

function bar() {
    foo();
    console.log("I am bar");
}

function square() {
    bar();
    console.log("I am square");
}

square();

Output:

I am bar
I am square
I am foo

I am foo will be printed after 5 seconds.

setTimeout() does not belong to core javascript, it is part of the browser's Web API module that can have n numbers of threads/processes to do the things in parallel.

foo gives the setTimeout responsibility to the Web API module. Web API module waits for 5 seconds and after 5 seconds it places the setTimeout callback function into a queue called callback queue.
Whenever the current Js function's call stack is empty, it picks the available callback from the callback queue and executes it. If the current function's call stack is not empty, none of the callbacks picked from the callback queue. This is the reason setTimeout's time parameter is the minimum wait time, not the exact time.



Ajax calls works in the same way. Ajax call request is forwarded to the Web API module and on success or failure, the Web API module places the success/failure callback with the data into the event queue.

After that whenever the current Js functions' stack becomes empty, callback entry from the callback queue is taken out and processed.

In the case of NodeJs, C++ modules take place of Web API and perform the File I/O, ajax and similar operations in parallel and whenever the result is ready pushed into the callback queue.

Hopefully, I am able to explain the event-loop magic.

Introduction to Rust programming language



For a long time, we are writing highly efficient applications/algorithms in C/C++.  C/C++ is always served the purpose and when it comes to speed and efficiency no other programming language is close to C/C++.
But at the same time, it requires high skills and experience for designing and development in C/C++. poorly designed applications always suffer when they come into the maintenance phase.

Memory safety has always been an issue for large scale C/C++ applications. People started using other high-level programming languages where speed/efficiency and high memory footprint are not only the prime requirement.
Combination of C/C++ with other high-level languages is also the trend now, core processing is managed by the C/C++ modules with non-critical modules are implemented in other high-level languages. 
This mix and match are widely accepted but these techniques suffer from poor support for C/C++ as these high level-languages are never designed for this purpose. For the web development, mobile application development, analytics, machine learning etc, a lot of good things are happening. But for system programming still, We can not see many new things.

Finally,  Mozilla research lab came with an entirely new open-source cross-platform language "Rust". Rust breaks down these barriers by eliminating the old pitfalls and providing a friendly, polished set of tools to help you along the way. Programmers who need lower-level control can do so with Rust, without taking on the risk of crashes or security holes. the language is designed to guide you naturally towards reliable code that is efficient in terms of speed and memory usage.

From Rust website (https://www.rust-lang.org)

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety

Key features 
  • zero-cost abstractions
  • move semantics
  • guaranteed memory safety
  • threads without data races
  • type inference
  • minimal runtime
  • efficient C bindings

Let us walk through the few highlights

Variable Mutability

fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

See the above program and assume if it is written in C/C++. We can say this is a valid program and outputs 5 and 6 on the console. 

but if we write into rust and compile, check what happens,

error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("The value of x is: {}", x);
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

By default Rust variables are immutable. This way Rust gives you the advantage of the safety and easy concurrency. However, you still have the option to make your variables mutable.

Rust has the mut keyword to make a variable mutable.

fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}



If we compile now


$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30 secs
     Running `target/debug/variables`
The value of x is: 5
The value of x is: 6

Note* mut and constant are not same. a constant variable always refers to a constant expression. It can not have an expression that has variables and can compute different values at runtime.


Ownership

Each value in Rust has a variable that’s called its owner.

fn main() {
    let s = String::from("hello");  // s comes into scope
    takes_ownership(s);             // s's value moves into the function 
println!("{}", some_string);    // It will not compile because s is no longer valid here
}

fn takes_ownership(some_string: String) { // some_string comes into scope
    println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing memory is freed.


There can only be one owner at a time of a value.

let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);

Above code compiles to errors

error[E0382]: use of moved value: `s1`
 --> src/main.rs:5:28
  |
3 |     let s2 = s1;
  |         -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value used here after move
  |
  = note: move occurs because `s1` has type `std::string::String`, which does
  not implement the `Copy` trait


When the owner goes out of scope, the value will be destroyed.

{
    let s = String::from("hello"); // s is valid from this point forward
    // do stuff with s
} // this scope is now over, and s is no longer valid




References and borrowing

Rust provides a way to use the value after passing to function, that is via reference (&). When we assign a value by reference it does not transfer the ownership, it just shares the reference to that object.

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Above program compiles and run without any issue. As s1 is passed as a reference to calculate_length() function, this function does not try to drop s1 at the completion of the function.

More details: https://doc.rust-lang.org/book/2018-edition/ch04-02-references-and-borrowing.html#references-and-borrowing

Ahh! It will be an injustice to the book that I read and trying to explain the Rust language concepts.
This book has everything to start with. I would strongly recommend this book to any beginner.

At last, I would say Rust-lang is a fantastic language along with its cool toolchain that makes system programming awesome without having fear of seg-fault and memory leak.


References:
https://www.rust-lang.org/en-US/
https://doc.rust-lang.org/book/2018-edition/foreword.html
https://www.youtube.com/watch?v=_jMSrMex6R0














Test the performance of flutter grid control (GridView)

Before giving a try for my production app, I wanted to test the performance of google flutter.
I tested it to the extreme and at last, I was surprised to see the performance.

  1. Create an image gallery type grid control 
  2. Add a new image to GridView every 10 milliseconds.
  3. Perform the scrolling as fast as I can.
Conclusion: Scrolling was buttery smooth at any time no matter images are getting added at every 10 milliseconds and the total number of items reached to 30 thousand.


Here is the source of test case

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:math';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Image grid demo",
      home: new HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  MyState createState() {
    return new MyState();
  }
}

class MyState extends State<HomePage> {
  MyState() {
    const duration = const Duration(milliseconds: 10);
    _timer = new Timer.periodic(duration, (Timer timer) {
      setState(() {
        int size = _random.nextInt(25) + 200;
        String url = 'https://placeimg.com/$size/$size/any';
        _items.add(url);

        if (_items.length > 30000)
          _timer.cancel();
      });
    });
  }

  Timer _timer;
  Random _random = new Random();
  List<String> _items = [];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.brown,
        title: new Text("Image Grid:" + _items.length.toString()),
      ),
      body: new Center(
        child: new GridView.count(
            crossAxisCount: 4,
            childAspectRatio: 1.0,
            padding: const EdgeInsets.all(5.0),
            mainAxisSpacing: 5.0,
            crossAxisSpacing: 5.0,
            children: _items.map((String url) {
              return new GridTile(
                child: new Image.network(url, fit: BoxFit.cover),
              );
            }).toList()),
      ),
    );
  }
}

Communication between widgets using InheritedWidget (Flutter)

I started using flutter and came accross the problem where I need communication between two widgets of my application.  I found InheritedWidget  easy and serve this purpose.

Let us make the problem simple.

  1. Button in App footer (MyFancyButton ) :On click on button increment the counter
  2. Counter widget (MyBox): It is in center of App.

Concept is simple. First create a StatefulWidget (MyApp/MyAppState) class that has count variable and a method (onTap) that increments the variable count.
In the build method of MyAppState return the InheritedWidget  (MyInheritedWidget)

Associate HomePage widget as a child to MyInheritedWidget.

  @override  Widget build(BuildContext context) {
     return new MyInheritedWidget(
      count: count,
      onTap: onTap,
      child: new HomePage(),
    );
  }
Now any change in count variable in State widget will result in rebuilding of child widget wherever MyInheritedWidget.

Complete code:
import 'package:flutter/material.dart';

void main() =>
    runApp(new MaterialApp(title: "Count Click App", home: new MyApp()));

class MyApp extends StatefulWidget {
  @override  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  int count = 0;
  void onTap() {
    setState(() {
      count++;
    });
  }

  @override  Widget build(BuildContext context) {
     return new MyInheritedWidget(
      count: count,
      onTap: onTap,
      child: new HomePage(),
    );
  }
}

class MyInheritedWidget extends InheritedWidget {
  final int count;
  final Function onTap;

  const MyInheritedWidget({Key key, this.count, this.onTap, child})
      : super(key: key, child: child);

  @override  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.count != count;
  }

  static MyInheritedWidget of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(MyInheritedWidget);
  }
}

class HomePage extends StatelessWidget {
  HomePage();

  @override  build(BuildContext context) {
    return new Scaffold(
      appBar:
          new AppBar(backgroundColor: Colors.amber, title: new Text("Count Click Demo")),
      body: new Center(child: new MyBox()),
      persistentFooterButtons: <Widget>[
        new MyFancyButton(),
      ],
    );
  }
}

class MyBox extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return new Center(
      child: new Text(
        "Counter: " + MyInheritedWidget.of(context).count.toString(),
        style: new TextStyle(fontWeight: FontWeight.w900, fontSize: 34.0),
      ),
    );
  }
}

class MyFancyButton extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return new RaisedButton(
      onPressed: () {
        MyInheritedWidget.of(context).onTap();
      },
      child: new Text("Click Me"),
      color: Colors.red,
      textColor: Colors.white,
    );
  }
}

Ionic2 multi columns Image Grid


I had a requirement to have an image grid-like image gallery.



I gone through the many tutorials and blogs. All were not suitable for my purpose.

  1. Some works with square sized images.
  2. Some works with hard-coded grid tile width.
  3. Some works on responsive design using fixed with image tile. I could not use this one because I need to use virtual-scroll.
  4. All work with the known number of items. All number of rows and columns are decided in the beginning.
I wanted to add image delete image and update image at the run time via some action without compromising the performance (with 10,000 image items). After searching here and there on Internet finally, I decided to sit calm and find the solution myself. After few hours a fairly simple solution came on the table.


Let's try with a sample application.


Create a blank App with the name 'ImageGrid'

ionic start ImageGrid

this will create the starting project. We will focus on the home.html, home.ts and home.scss only.

Image grid can be visualized as a 2D matrix with a fixed number of columns and variable numbers of row.
As I came from C/C++ background and know that internally 2D array is a contiguous memory allocation. So I decided to handle the 2D image matrix like a simple array.

Check the basic concept

// Create a type, you can add more fields to this type as per your requirement.
interface FileObject {
  public thumbnail: string;
}

const _grid_columns_count: number = 3; // Number of columns in image grid

//Get a specific item by row and column
yourFunction(row: number, col: number) {
  let i = row * _grid_columns_count + col;
}
// Here i is index by which you can query an item by row and column.
Full Source code
Home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

interface FileObject {
  thumbnail: string;
}

const _grid_columns_count: number = 3; // Number of columns in image grid

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  private columns: Array<number>;
  private rows: Array<number>;
  private fileObjects: FileObject[];


  constructor(public navCtrl: NavController) {
    // Create column array for number of columns you want
    this.columns = new Array(_grid_columns_count);

    // This array will hold the number of rows
    this.rows = new Array<number>();

    // This array will hold all the items in the grid.
    // Add a item by appending or inserting
    // Remove a item by delete your item from the array
    this.fileObjects = new Array<FileObject>();
  }

  // Add item
  addItem(obj: FileObject) {
    this.fileObjects.push(obj);

    // true of if condition indicates that we need a new row.
    if ((this.rows.length * _grid_columns_count) < this.fileObjects.length) {
      this.rows.push(this.rows.length);
    }
  }

  // Get an item by row and column
  getItemThumbnail(row: number, col: number) {
    let i = row * _grid_columns_count + col;

    if (i < this.fileObjects.length) {
      return this.fileObjects[i].thumbnail;
    }
    else {
      return "no found";
    }
  }

  isValid(row: number, col: number): boolean {
    let i = row * _grid_columns_count + col;
    return (i < this.fileObjects.length);
  }

  onTapImage(row, col) {
    let i = row * _grid_columns_count + col;

    if (i < this.fileObjects.length) {
      alert(this.fileObjects[i].thumbnail);
    }
  }

  getTileHeight(): string {
    return "100px;"
  }

  /*
  This is a method just to simulate how we can items
  change the image path as per your wish
*/
  addImages() {
    for (let i = 0; i < 8; ++i) {
      let obj: FileObject = {
        thumbnail: 'url("../assets/icon/image.jpg")'
      }

      this.addItem(obj);
    }
  }
}
Home.html
<ion-header>
  <ion-navbar color="dark">
    <ion-title>
      {{fileObjects.length}} files
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding style="background-color:#222">

  <ion-list [virtualScroll]="rows" approxItemHeight="{{getTileHeight()}}" no-margin>
    <ion-row *virtualItem="let row" class="item-row">
      <ion-col *ngFor="let column of columns; let col = index">
        <div *ngIf="isValid(row, col)" [style.background-image]="getItemThumbnail(row, col)" class="image-background" (tap)="onTapImage(row, col)">
        </div>
      </ion-col>
    </ion-row>
  </ion-list>

</ion-content>

<ion-footer>
  <ion-toolbar color="dark" style="text-align:center;">
    <!-- Button just to trigger the adding items -->
    <button ion-button round (tap)="addImages()">Add Images</button>
  </ion-toolbar>
</ion-footer>
Home.scss
page-home {
    .item-row {
        width: 100%;
        height: 120px;
    }
    .image-background {
        border: 2px solid #222;
        background-color: rgba(92, 90, 87, 0.644);
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        height: 100%;
    }
}


You can find the working project at Github
https://github.com/Anil8753/ImageGrid

Be smart with pointers in C++11

First of all, we need to understand the need of smart pointers.  We have calloc/malloc and free in C and new and delete/delete[] in C++98. Smart programmers use them smartly, but a smart programmer can also make mistakes that can lead to memory leaks.
I do not have any evidence but can say even Microsoft engineers (assuming they are very smart) also left memory leaks in Windows XP. I remember the days when I used to leave the Windows XP running for a week and seen XP becomes unresponsive. It was working fine after restarting the system.

Problem faced with traditional pointers:

  • Forgot to delete object allocated at heap, or when exceptions happen (memory leak).
  • Dangling pointers (more than one pointers are pointing to the same object and object is deleted by one the pointers.
  • Managing lifetime of the pointers

C++98 introduced auto_ptr to manage naked pointers

When auto_ptr is assigned to another auto_ptr, it transfers the ownership of containing object as well. In the given example, autoPtr2 has the ownership of the object. When autoPtr2 goes out of scope, it deletes the object as well. Now autoPtr1 becomes the dangling pointer and accessing it leads to the crash.

    try
    {
        auto_ptr<YourClass> autoPtr(new YourClass());
        // write some code that can throw exception. (e.g. divide by zero)
    }
    catch (...)
    {
    }

This is safe code, it give the assurance of freeing the allocated memory even exception happens (memory gets freed on stack unwinds).

Do not think that auto_ptr is smart and  perfect, it also lacks in the situation following.

class YourClass
{
public:
    int m_data = 10;
};

int main()
{
    auto_ptr<YourClass> autoPtr1(new YourClass());
    {
        auto_ptr<YourClass> autoPtr2 = autoPtr1;
    }
    cout << autoPtr->m_data;

    return 0;
}

The same situation comes while passing auto_ptr as the function parameter. In this case also, ownership is transferred to function's receiving parameter and when the function ends, deletes the object as well.


class YourClass
{
public:
    int m_data = 10;
};

void TestFunction(auto_ptr<YourClass> autoPtr)
{
    cout << autoPtr->m_data;
}

int main()
{
    auto_ptr<YourClass> autoPtr(new YourClass());
    TestFunction(autoPtr);
    cout << autoPtr->m_data;

    return 0;
}

Also auto_ptr can not be used to create the array of pointers of objects. means following creates the disaster.

auto_ptr<YourClass> autoPtr(new YourClass[10]);

As auto_ptr calls the delete internally not delete[], when it goes out of scope.

C++11 introduced new set of pointers to solve the problem with naked pointer and auto_ptr

  • shared_ptr
  • unique_ptr
  • weak_ptr

shared_ptr
shared_ptr works by implementing reference counting mechanism. When a shared_ptr is assigned to another shared_ptr, it shares the object instead of transferring the ownership like auto_ptr does. Also, it increases the reference count by 1. shared_ptr reference count is also called strong reference count.


{
    shared_ptr<YourClass> sharedPtr1(new YourClass); // reference count = 1
    {
        shared_ptr<YourClass> sharedPtr2(sharedPtr1); // reference count = 2
        {
            shared_ptr<YourClass> sharedPtr3 = sharedPtr2; // reference count = 3
        } // reference count = 2
    } // reference count = 1
} // reference count = 0 and objct gets deleted

As soon as any shared_ptr goes out of scope, reference count decrease by 1 and reference count becomes 0, object gets deleted.

you can create the shared_ptr to the array of objects:


    shared_ptr<YourClass> sharedPtr(new YourClass[10], [](YourClass* ptr)
                                                            { 
                                                                delete[] ptr;
                                                            });

To make sure that it calls delete[] instead of delete, we have to mention it via lambda.

Do you think that shared_ptr is perfect? 

No!!!, nothing is perfect in this world, so how can shared_ptr be?

consider the situation like:


int main()
{
    YourClass* pYourClass = new YourClass();
    shared_ptr<YourClass> sharedPtr1(pYourClass);  // sharedPtr1 ref count == 1
    shared_ptr<YourClass> sharedPtr2(pYourClass);  // sharedPtr2 ref count == 2

    return 0;
}

When sharedPtr2 goes out of scope, it deletes the object. When sharedPtr1 goes out of scope, it does not have anything to be deleted and hence  you will get CRASH!!!.

So make a thumb rule, never create share_ptr from naked pointers.


Create shared_ptr only by the followings:

    shared_ptr<YourClass> sharedPtr1(new YourClass());
    // or
    shared_ptr<YourClass> sharedPtr2 = make_shared<YourClass>();

Another issue with shared_ptr (cyclic dependency)


class First
{
public:
    shared_ptr<Second> m_sharedPtrSecond = nullptr;
};

class Second
{
public:
    shared_ptr<First> m_sharedPtrFirst = nullptr;
};

int main()
{
    // Reference count of sharedPtrFirst == 1
    shared_ptr<First> sharedPtrFirst(new First());

    // Reference count of sharedPtrSecond == 1 
    shared_ptr<Second> sharedPtrSecond(new Second());

    // Reference count of sharedPtrSecond == 2 
    sharedPtrFirst->m_sharedPtrSecond = sharedPtrSecond;

    // Reference count of sharedPtrFirst == 2
    sharedPtrSecond->m_sharedPtrFirst = sharedPtrFirst;

    return 0;
}


When main ends:
  1. sharedPtrSecond goes out of scope, it decreases the reference count by 1 and final reference count is still 1. The object of class Second does not gets deleted.
  2. Similarly when sharedPtrFirst goes out of scope, reference count is still 1 and object of class First does not get deleted. 

We can see there are clear memory leaks in case of cyclic dependencies.

To solve this cyclic dependency problem, C++11 provides another smart pointer, called weak_ptr.


weak_ptr

Unlike shared_ptr, weak_ptr does not increase the string reference count but increases the special weak reference count. weak_ptr is created from shared_ptr. Assigning a weak pointer to another weak pointer increases the weak ref count.


int main()
{
    // strong ref count == 1
    shared_ptr<YourClass> sharedPtr(new YourClass);

    // strong ref count == 1, weak ref count == 1
    weak_ptr<YourClass> weakPtr1(sharedPtr);
    // strong ref count == 1, weak ref count == 2
    weak_ptr<YourClass> weakPtr2 = weakPtr1;

    return 0;
}

As it does not increase the strong ref count, it simply does not hold the ownership of the object.
If a shared_ptr(having strong ref count 1) goes out of scope, it simply deletes the object, no matters how many weak references still exists. All the weak_ptr, referring to this shared_ptr, become invalid.

Before using weak_ptr, you must check the validity of the existence using the expired() function.


    weak_ptr<YourClass> weakPtr;
    {
        shared_ptr<YourClass> sharedPtr(new YourClass);
        weakPtr = sharedPtr;
    }

    // weakPtr.expired() will return true here.
    if (weakPtr.expired() == false)
    {
        // safe code
    }

(*->) are not allowed with weak_ptr unlike other pointers. As it is not the owner of the object and does not let the programme mishandle it. 
To use weak_ptr, simply create shared_ptr from the weak_ptr by using the lock(). It increases the strong ref count by 1. Now while using it, we are assured about the existence of the object.

int main()
{
    weak_ptr<YourClass> weakPtr;
    shared_ptr<YourClass> sharedPtrFromWeakPtr;

    {
        shared_ptr<YourClass> sharedPtr(new YourClass);
        weakPtr = sharedPtr;

        sharedPtrFromWeakPtr = weakPtr.lock();
    }
    // weakPtr.expired() will return false here
    if (weakPtr.expired() == false)
    {
        // safe code
    }

    return 0;
}


Just see how cyclic dependency problem is resolved by weak_ptr

class Second;

class First
{
public:
    weak_ptr<Second> m_weakPtrSecond;
};

class Second
{
public:
    weak_ptr<First> m_weakPtrFirst;
};

int main()
{
    // strong ref count ==1
    shared_ptr<First> sharedPtrFirst(new First);

    // strong ref count == 1
    shared_ptr<Second> sharedPtrSecond(new Second);

    // strong ref count ==1, weak ref count ==1
    sharedPtrFirst->m_weakPtrSecond = sharedPtrSecond;

    // strong ref count ==1, weak ref count ==1
    sharedPtrSecond->m_weakPtrFirst = sharedPtrFirst;

    return 0;
}
// main ends
// sharedPtrSecond goes out of scope, strong ref == 0 and weak ref == 1
// object gets deleted as strong ref ==0

// sharedPtrFirst goes out of scope, strong ref == 0 and weak ref == 1
// object gets deleted as strong ref ==0


unique_ptr

We can say it is the improvement over error prone auto_ptr. unique_ptr is the only owner of the object, no two unique_ptr should not point to the same object.

The object is destroyed and its memory deallocated when either of the following happens:

  • unique_ptr managing the object is destroyed
  • unique_ptr managing the object is assigned another  pointer via operator= or reset().

It gives the guarantee of releasing the memory always.

int main()
{
    unique_ptr<YourClass> uniquePtr(new YourClass);

    // deletes the old YourClass object,
    // now uniquePtr points to new YourClass object
    uniquePtr = unique_ptr<YourClass>(new YourClass);

    // This is the another way to delete the YourClass object
    uniquePtr.reset();

    return 0;
}


int main()
{
    std::unique_ptr<YourClass> uniquePtr1;
    {
        std::unique_ptr<YourClass> uniquePtr2(new YourClass);

        // uniquePtr1 = uniquePtr2; // Error ! can't copy unique_ptr
        uniquePtr1 = std::move(uniquePtr2);
 
        // YourClass instance will continue to live, 
        // despite uniquePtr2 going out of scope
    }
    return 0;
}


We can create the array of object and we do not need to provide the special delete instructions. It has the proper syntax for creating the array.

int main()
{
    // When uniquePtr goes out of scope, calls the delete
    unique_ptr<YourClass> uniquePtr(new YourClass);

    // When uniquePtrArray goes out of scope, calls the delete[]
    unique_ptr<YourClass[]> uniquePtrArray(new YourClass[10]);

    return 0;
}


For more reading:
http://www.umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
http://en.cppreference.com/w/cpp/memory/auto_ptr
http://en.cppreference.com/w/cpp/memory/weak_ptr
http://en.cppreference.com/w/cpp/memory/shared_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr


boost based Publisher/Subscriber framework in C++

Find full implementation https://github.com/Anil8753/CppPubSub
Boost based Publisher/Subscriber framework in C++. One can subscribe for a channel and another can publish the notification on the same channel.
Note: It has the dependency on boost. Please download boost library and set the boost path in project settings (CppPubSub.vcxproj). I tested on Windows only, but it should be portable to other platforms as well. Full sample code is available in Source.cpp.

Usage:


// you should create a singleton object of NotificationService class, make it accessible throughout your application. 
INotificationService* pNotificationService = new NotificationService();

// Subscribe for the event.
function<NotificationHandler> fnNotificationHandler
    = bind(&SubscriberClass::NotificationHandlerFunction, this, std::placeholders::_1);

subscriptionToken = pNotificationService->Subscribe("TEST_CHANEL", fnNotificationHandler);

// Publish event
NotificationData _data;
_data["data1"] = "Hello";
_data["data2"] = "World";
pNotificationService->Publish("TEST_CHANEL", _data);

// Unsubscribe event.
pNotificationService->Unsubscribe(subscriptionToken);


Full Usage:

#include "windows.h"
#include "NotificationService.h"

#define TEST_CHANEL "TestChanel"

typedef boost::shared_ptr<INotificationService> INotificationServicePtr;

class SubscriberClass
{
private:
    INotificationServicePtr m_pNotificationService;
    SubscriptionToken       m_SubscriptionToken;

public:
    SubscriberClass(INotificationServicePtr pNotificationService)
        :m_pNotificationService(pNotificationService)
    {
        SubscribeForNotiications();
    }

    ~SubscriberClass()
    {
        m_pNotificationService->Unsubscribe(m_SubscriptionToken);
    }

    void SubscribeForNotiications()
    {
        function<NotificationHandler> fnNotificationHandler
            = bind(&SubscriberClass::NotificationHandlerFunction, this, std::placeholders::_1);

        m_SubscriptionToken =
            m_pNotificationService->Subscribe(TEST_CHANEL, fnNotificationHandler);
    }

    void NotificationHandlerFunction(const NotificationData& data)
    {
        NotificationData _data = data;

        cout << _data["data1"] << endl;
        cout << _data["data2"] << endl;
        cout << "------------" << endl;
    }
};

class PublisherClass
{
public:
    PublisherClass(INotificationServicePtr pNotificationService)
        :m_pNotificationService(pNotificationService)
    {
        PublishNotifications();
    }

    ~PublisherClass()
    {
    }

private:
    void PublishNotifications()
    {
        INotificationServicePtr pNotificationService = m_pNotificationService;

        thread publishThread = std::thread{ [pNotificationService]() {

            while (true)
            {
                NotificationData _data;
                _data["data1"] = "Hello";
                _data["data2"] = "World";

                pNotificationService->Publish(TEST_CHANEL, _data);

                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        } };

        publishThread.detach();
    }

    INotificationServicePtr m_pNotificationService;
};

int main()
{
    INotificationServicePtr     pNotificationService(NotificationService::GetNotificationService());
    SubscriberClass             objSubscriberClass(pNotificationService);
    PublisherClass              objPublisherClass(pNotificationService);

    getchar();

    return 0;
}


Total Pageviews