C++11 regex using g++

Boost regex has been accepted into C++11. So, I decided to give it a try using g++.

#include<iostream>
#include<string>
#include<regex>

using namespace std;

int main() {
        string str("2 a\n3 b\n4 c\n5 d\n6 c");
        regex r("[0-9]");

        regex_iterator<string::iterator> start(str.begin(), str.end(), r);
        regex_iterator<string::iterator> end;

        while(start != end) {
                cout << start->str() << endl;
                ++start;
        }
}

I was surprised to get a big fat link-time error:

/tmp/cc80j8Z8.o: In function `main':
regex1.cpp:(.text+0x133): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::regex_iterator(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>, std::basic_regex<char, std::regex_traits > const&, std::bitset)’
regex1.cpp:(.text+0x13f): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::regex_iterator()’
regex1.cpp:(.text+0x150): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator->()’
regex1.cpp:(.text+0x1a9): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator++()’
regex1.cpp:(.text+0x1bf): undefined reference to `std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits >::operator!=(std::regex_iterator<__gnu_cxx::__normal_iterator<char*, std::string>, char, std::regex_traits > const&)’
collect2: error: ld returned 1 exit status

Seems like gcc 4.8.2, delivered by my distribution doesn’t support regex yet. So, we are forced to use Boost regex for now. Or use g++ 4.9.0 instead, which has regex implemented. To install the latest g++ release, execute the following command in the terminal:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install g++-4.9

To compile the code with g++4.9:

g++-4.9 --std=c++11 regex1.cpp -o regex1

C++ collection: how are objects stored

Note: In this article, we will use vectors for demonstration. But the same applies for all collections in C++.

Have you wondered, how C++ STL stores objects in its storage and its consequences? That is exactly what we are going to discuss today. When you insert, push_back, assign, etc an object into C++ STL collections, the default behavior is C++ copies the object using copy constructor and stores the newly created object. One obvious consequence of this is that, changes made to the original object inserted has no effect on the object stored.

Output:

Original before modification: 5
Original after modification: 6
Stored after modification: 5

Another consequence and the most important consequence occurs when the class has dynamically allocated members. The default copy constructor provided by C++ does a shallow copy of these pointers. This will lead to segmentation faults when the objects are being destructed.

Output:

copy constructor Data(const Data &d)
1
2
3
4
5

destructor
*** Error in `./copy_problems': double free or corruption (fasttop): 0x00000000021f4010 ***
Aborted (core dumped)

So, how do we overcome this issue? Below we will discuss various ways in which this problem can be fixed.

Vector of pointers to objects

One of the easiest way to achieve this is by creating a vector of pointers to objects instead of vector of objects. This makes sure that the object stored is the object inserted.

It should be noted that automatic variables created on stack should not be stored this way, if the vector could be passed out of the function. This is because when the function frame is unrolled, the object allocated on the stack is destroyed.

Note: In C++, vector of reference to objects is not possible.

Vector of shared_ptr to objects

As you might have noticed, the previous solution has two problems:

  • Objects should be allocated in heap
  • The destruction of the object is left to the developer. This could lead to serious problems!

The obvious solution to fix the problems with previous solution is to use shared_ptr instead of raw pointers. shared_ptr keeps reference counts and destructs the object when there are no references left to the object. This works well because methods that remove elements from vector calls the destructor of the element being removed.

Use move semantics instead of copy semantics

C++ STL collections allow the use of move semantics instead of copy semantics to clone the object being inserted. I will dedicate an entire post for this solution.

C++11: How to create cyclic dependencies with shared_ptr and how to avoid them

C++ smart pointers are god send to C++ programmers. It avoids dealing with raw pointers and takes care of resource deallocation when the pointed “whatever” goes out of scope. All great. But there does exist some pitfalls and we should be vary of them. One such pitfalls is cyclic dependency when using shared_ptr. Cyclic dependency occurs when there is self-reference either in its own member or through the member of a member or through the member of a member of a member…. ok. I will stop. You get it :P.

Cyclic dependency

Cyclic dependency

Creating cyclic dependency

First we will see how we can create a cyclic dependency. Then we will see how to avoid them by using weak pointers.

Here we show two ways to create cyclic dependency:

  1. Cyclic dependency due to a self-referencing member
  2. Cyclic dependency due to a member of a member referencing this

Case 1

When ptr is created, its count is initialised to 1. When it is assigned to ptr->a, its count is incremented by 1 to 2. What this means is that ptr will not be deleted until both ptr and ptr->a are reset. But there is no way for that to happen. When ptr goes out of scope, the count will be decremented by 1 to 1. Since the count is not 0, ptr will not be deleted. ptr->x will not be reset until ptr is deleted. ptr will not be deleted until ptr->x is reset.
So shortly: ptr cannot be released because ptr->x will not be reset until ptr is reset.

Case 2

When x is created, its count is initialised to 1. When it is assigned to x->b->a, its count is incremented by 1 to 2. What this means is that x will not be deleted until both x and x->b->a are reset. But there is no way for that to happen. When x goes out of scope, the count will be decremented by 1 to 1. Since the count is not 0, x will not be deleted. Since x is not deleted, x->b will be not be deleted. Since x->b will not be deleted, x->b->a will not be deleted. If x->b->a will not be deleted, x will not be deleted. Go back 3 lines and start reading again and again and again :P.
So shortly: x(and hence x->b) will not be released because x->b->a will not be reset until x is reset.

Solving cyclic dependency using weak_ptr

Changing the self-referencing member a of ClassA to weak_ptr fixes the cyclic dependency problem in case 1.
Changing the member a of ClassB to weak_ptr fixes the cyclic dependency problem in case 2.

Courtesy: Stackoverflow

Linux: Detecting and adding fan control

I bought a Zotac EI750 HTPC recently. It has very good specs but its fan gets noisy very too often. Ubuntu by default doesn’t detected EI750′ fan. I installed lm-sensors and tried sensors command.

sudo apt-get install lm-sensors
sudo sensors

Sensors listed my CPU thermal sensors correctly but couldn’t find the fans.

acpitz-virtual-0
Adapter: Virtual device
temp1: +27.8°C (crit = +105.0°C)
temp2: +29.8°C (crit = +105.0°C)

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0: +40.0°C (high = +84.0°C, crit = +100.0°C)
Core 0: +36.0°C (high = +84.0°C, crit = +100.0°C)
Core 1: +37.0°C (high = +84.0°C, crit = +100.0°C)
Core 2: +35.0°C (high = +84.0°C, crit = +100.0°C)
Core 3: +38.0°C (high = +84.0°C, crit = +100.0°C)

This means that the driver for the fan is not loaded. I should find what fan my system has and load its driver. So, I executed sensors-detect to see if lm-sensors can find the fan.

sudo sensors-detect

Luckily, it did!!! I have Nuvoton NCT5532D/NCT6779D and the corresponding driver is nct6775.


Found `Nuvoton NCT5532D/NCT6779D Super IO Sensors’ Success!
(address 0xa10, driver `nct6775′)

Driver `nct6775′:
* ISA bus, address 0xa10
Chip `Nuvoton NCT5532D/NCT6779D Super IO Sensors’ (confidence: 9)

Now, its easy! Load nct6775 module.

sudo modprobe nct6775

Sensors should detect your fan now.

sensors


fan1: 0 RPM (min = 0 RPM)
fan2: 2246 RPM (min = 0 RPM)
fan3: 0 RPM (min = 0 RPM)
fan4: 0 RPM (min = 0 RPM)
fan5: 0 RPM (min = 0 RPM)

Gnome3: Enable suspend/hibernate option without swap partition

Linux needs swap partition to suspend or hibernate. But there is a way to enable suspend and hibernate without creating a swap partition. The trick is to create a swap file instead of partition and informing linux to use this swap file instead of swap partition.

Install pmi(power management interface) package

sudo apt-get install powermanagement-interface

Now you should be able to suspend using either

sudo pm-suspend

or

dbus-send --print-reply --system --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.Suspend

Peculiarly for me, the screen doesn’t lock when the PC suspends. Alternatively, you can lock and suspend using the following command

gnome-screensaver-command -l && dbus-send --print-reply --system --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.Suspend

Enable suspend option in Gnome3 status menu

You can enable suspend option in Gnome3 status menu by installing the following extension.

C++: vector of arrays

In C++ arrays cannot be stored in vectors. This restriction is due to the fact that arrays cannot be copy constructed or assigned. For example, this won’t compile in c++

To work around this limitation, c++11 has introduced a new container called std::array. std::array is just a template class that encapsulates a static array. It cannot be resized and its size should be know at compile time. Here is a small example on how to create a vector of arrays.

SystemVerilog: Connect interface to pure Verilog modules

SystemVerilog interfaces gives us a very good tool to make the code cleaner and less error prone. If you have a group of ports that go together, you can group them into a single interface and reduce huge amount of code.


Thats great. But if you have a pure verilog module and want it to stay that way. How should we connect the interface to the pure Verilog module? Its easy as well. Just create an instance of a module and an instance of the interface. When you instantiate the verilog module use the interface’s members as module’s ports. Now you can drive your module through the interface or connect the module to another SystemVerilog module that accepts the same interface.


Passing and receiving different SystemVerilog datatypes with C/C++ using DPI

SystemVerilog makes interaction with C/C++ a piece of cake. Now, you can directly call C/C++ functions as functions or tasks in SystemVerilog(aka. Importing) and call SystemVerilog functions or tasks from C/C++(aka. Exporting). In this article, we will see how we can pass and receive different SystemVerilog datatypes through DPI.

Return type of imported C/C++ functions

First thing to note is that imported functions can only return single bit types and 2-state int or double types that are not vectors.

This rule rules out all 4-state types except single bit types

  • logic packed arrays, logic unpacked arrays
  • wire, wire packed arrays, wire unpacked arrays
  • reg, reg packed arrays, reg unpacked arrays

and all vector types

  • bit packed arrays, bit unpacked arrays
  • logic packed arrays, logic unpacked arrays
  • wire packed arrays, wire unpacked arrays
  • reg packed arrays, reg unpacked arrays

So what we are left with are fixed width int and double types:

  • bit
  • byte
  • shortint
  • int
  • shortreal
  • real
  • logic

You can pass these types as arguments and receive these types as return from an imported functions. Here is an example of passing and receiving single bit bit and logic.

import "DPI-C" context function bit and_bit(input bit a, b);
import "DPI-C" context function logic and_logic(input logic a, b);
svBit
and_bit(
    svBit a,
    svBit b) {
	return a && b;
}

svLogic
and_logic(
    svLogic a,
    svLogic b) {
	return a && b;
}

You should have noticed two new types on C/C++ side: svBit and svLogic. These are usually 8 bit unsigned char types but only the lsb bit is used.

Passing and receiving packed arrays

Passing and receiving packed arrays is easier than dealing with unpacked arrays. On C side, packed bit vectors are called svBitVecVal and packed logic vectors are called svLogicVecVal. Bit vectors are plain int types. If the vector size exceeds the size that can be stored inside an integer, the bit vectors are passed as array of svBitVecVal.
Logic vectors are little bit more complicated because they represent 4-state values. svLogicVecVal is a structure with two members aval and bval. aval stores the plain bit representation of logic vector while bval stores whether the corresponding bit is ‘0’, ‘1’ or ‘x’, ‘z’. If the vector size exceeds the size that can be stored inside an integer, the logic vectors are passed as array of svLogicVecVal.

[ada]
import “DPI-C” context function void add_bpv(input bit [3:0] a, b, output bit [3:0] c);
import “DPI-C” context function void add_lpv(input logic [3:0] a, b, output logic [3:0] c);
[/ada]

void
add_bpv(
    const svBitVecVal* a,
    const svBitVecVal* b,
    svBitVecVal* c) {
	*c = *a + *b;
}

void
add_lpv(
    const svLogicVecVal* a,
    const svLogicVecVal* b,
    svLogicVecVal* c) {
	c->aval = a->aval + b->aval;
	c->bval = 0;
}

As you can see, we are using output arguments to receive vector types because imported functions cannot return vector types.

Passing and receiving unpacked vectors

Unpacked arrays are sent as arrays of svBit or scLogic to C. There is no way to directly access the integer represented by putting all the individual bits together without calculating it.

import "DPI-C" context function void and_buv(input bit a[3:0], b [3:0], output bit c [3:0]);
import "DPI-C" context function void or_luv(input logic a[3:0], b [3:0], output logic c [3:0]);
void
and_buv(
    const svBit* a,
    const svBit* b,
    svBit* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] & b[i];
	}
}
void
or_luv(
    const svLogic* a,
    const svLogic* b,
    svLogic* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] | b[i];
	}
}

Passing and receiving mixed packed and unpacked arrays

As expected, mixed packed and unpacked arrays are represented as arrays of svBitVecVal or svLogicVecVal. If the size of the packed dimension is greater than what can fit inside an integer, mixed packed and unpacked arrays are represented as arrays of arrays of svBitVecVal or svLogicVecVal.

import "DPI-C" context function void add_bpuv(input bit [0:3]a[0:3], b [0:3], output bit [0:3]c [3:0]);
void
add_bpuv(
    const svBitVecVal* a,
    const svBitVecVal* b,
    svBitVecVal* c) {
	for(int i = 0; i < 4; i++) {
		c[i] = a[i] + b[i];
	}
}

Passing and receiving structs

Structs are passed can be passed and received directly. Individual members are representing based on their data type as discussed above.

typedef struct {
shortint mem1;
logic [7:0] mem2;
bit [7:0] mem3;
} struct_t;

import "DPI-C" context function void add_struct(input struct_t a, b, output struct_t c);
void
add_struct(
    const struct_t* a,
    const struct_t* b,
    struct_t* c) {
	c->mem1 = a->mem1 + b->mem1;
	c->mem2[0].aval = a->mem2[0].aval + b->mem2[0].aval;
	c->mem2[0].bval = 0;
	c->mem3[0] = a->mem3[0] + b->mem3[0];
}

Here is the full verilog and c code.