Fixed-size block allocator
About thread safety: it is not thread safe. There is nothing that prevents member-functions such as  TFixedAllocator::allocate,  TFixedAllocator::new_pool and others to be executed by multiple threads at the same time.  Inside these functions several variables are modified. Modifying them from multiple threads without synchronization is an undefined behavior according to the C++ standard. 

How to fix it? The easiest way to do it is to use one std::mutex for the allocate and deallocate member-functions of the TFixedAllocator class(acquiring it in the very beginning of the function and releasing it in the very end). It is convenient to use an std::lock_guard for this purpose. Something like this:

template &lt;size_t ChunkSize&gt;
class TFixedAllocator {
    ...

    std::mutex allocator_mutex;

public:
    ...

    void* allocate() {
        std::lock_guard&lt;std::mutex&gt; allocator_lock_guard(allocator_mutex);
        if (!free) {
            new_pool();
        }
        TNode* result = free; // allocate the topmost element (saved in free)
        free = free-&gt;next; // and pop it from the stack of free chunks
        return static_cast&lt;void*&gt;(result);
    }

    void deallocate(void* elem) {
        std::lock_guard&lt;std::mutex&gt; allocator_lock_guard(allocator_mutex);
        TNode* node = static_cast&lt;TNode*&gt;(elem);

        // add to the stack of chunks
        node-&gt;next = free;
        free = node;
    }
};

Functions and variables naming: it is conventional to name functions with a verb(to describe an action). I would use get_instance instead of instance and create_new_pool instead of new_pool, for example. 
You TFixedAllocator class violates the single responsibility principle. Despite managing memory allocation(which is its main responsibility) it also implicitly implements some data structure(a stack?(I mean things related to the union TNode, the free pointer and so on)). It makes the code rather hard to follow: those operations with free and next pointers are not easy to understand(it is not clear why they are performed in the first place). There are two ways to fix it: 


Create a separate class that implements this data structure.
Use a standard container. If what you need is a stack, std::stack is a good option(again, I'm not completely sure if it is feasible because I do not fully understand how this data structure is used in your code).

Writing useless comments is definitely a bad practice. For instance, union TNode { // union doesn't make much sense: it is absolutely clear that it is a union without any comments. I'd recommend simply deleting comments like this one. Comments inside a function that tell what a block of code does, like here:

void deallocate(void* elem) {
    TNode* node = static_cast&lt;TNode*&gt;(elem);

    // add to the stack of chunks
    node-&gt;next = free;
    free = node;
}


usually indicate that this block of code should have been a separate function(in this case, as I have mentioned before, there should probably be another class that implements this data structure). In general, you should try to write self-documenting code. 
Spacing and indentation: separating different functions with an empty line makes the code more readable.