#include"WCMemSTDC.h" 
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<stdio.h>
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
static pthread_key_t usage_key;
/*!
 * \ingroup MemoryManager
 * \brief Выделение памяти c обнулением буфера
 */
void mark_alloced()
{
    pthread_setspecific(usage_key,0);
}
void check_alloced()
{
    size_t size_alloced=(size_t)pthread_getspecific(usage_key);
    if (size_alloced)
    {
	printf("Error:thread:%llx:unfreed:%d",(unsigned long long)pthread_self(),(unsigned)size_alloced);
	abort();
    }
}
static DWORD CPCAPI
stdAllocMemory(LPCPC_MEMORY_ARENA pArena, SIZE_T dwSize, DWORD dwMemPoolId,
	       DWORD dwThreadId, LPVOID *pRes)
{
  void *ptr;
  size_t size_alloced;

  UNUSED(dwThreadId);
  UNUSED(dwMemPoolId);


  size_alloced=(size_t)pthread_getspecific(usage_key);
  ptr = malloc(dwSize+sizeof(size_t));
  if(!ptr){
    return NTE_NO_MEMORY;
  } 
  memset (ptr, 0, dwSize+sizeof(size_t));
  *(size_t *)ptr=dwSize;
  *pRes = (size_t *)ptr+1;
  size_alloced+=dwSize;
  pthread_setspecific(usage_key,(void *)size_alloced);

  return S_OK;
}

/*!
 * \ingroup MemoryManager
 * \brief Освобождение памяти
 */
static DWORD CPCAPI
stdFreeMemory(LPCPC_MEMORY_ARENA pArena, VOID *pMem, DWORD dwMemPoolId)
{
  size_t size_alloced;
  size_t * ptr=((size_t *)pMem)-1;
  UNUSED(dwMemPoolId);
  size_alloced=(size_t)pthread_getspecific(usage_key);
  size_alloced-=*ptr;
  free (ptr);
  pthread_setspecific(usage_key,(void *)size_alloced);

  return 0;
}

static void CPCAPI
stdValidateMemory(LPCPC_MEMORY_ARENA pArena)
{
}

static void CPCAPI
stdStatMemory (LPCPC_MEMORY_ARENA pArena, LPCPC_MEMORY_STATS pStats,
	       DWORD dwMemPoolId)
{
    UNUSED (pArena);
    UNUSED (pStats);
    UNUSED (dwMemPoolId);
}

static void CPCAPI
stdDoneMemory(LPCPC_MEMORY_ARENA pArena)
{
}

DWORD CPCAPI stdInitMemory(LPCPC_MEMORY_ARENA *pArena, LONG *PoolSizes, DWORD nPools)
{
  static CPC_MEMORY_ARENA Config;
  pthread_key_create(&usage_key,0);
  memset (&Config, 0, sizeof (Config));
  Config.pValidateMemory = stdValidateMemory;
  Config.pDoneMemory = stdDoneMemory;
  Config.pAllocMemory = stdAllocMemory;
  Config.pFreeMemory = stdFreeMemory;
  Config.pStatMemory = stdStatMemory;
  *pArena = &Config;
  return S_OK;
}

void CPCAPI CPCSetLocks(LPCPC_CONFIG pConfig)
{
    UNUSED(pConfig);
}

