How avoid using global variable when using nftw

落爺英雄遲暮 提交于 2019-11-28 11:13:02

No. nftw doesn't offer any user parameter that could be passed to the function, so you have to use global (or static) variables in C.

GCC offers an extension "nested function" which should capture the variables of their enclosing scopes, so they could be used like this:

void f()
{
  int i = 0;
  int fn(const char *,
    const struct stat *, int, struct FTW *) {
    i++;
    return 0;
  };
  nftw("path", fn, 10, 0);
}

Using ftw can be really, really bad. Internally it will save the the function pointer that you use, if another thread then does something else it will overwrite the function pointer.

Horror scenario:

thread 1:  count billions of files
thread 2:  delete some files
thread 1:  ---oops, it is now deleting billions of 
              files instead of counting them.

In short. You are better off using fts_open.

If you still want to use nftw then my suggestion is to put the "global" type in a namespace and mark it as "thread_local". You should be able to adjust this to your needs.

/* in some cpp file */
namespace {
   thread_local size_t gTotalBytes{0};  // thread local makes this thread safe
int GetSize(const char* path, const struct stat* statPtr, int currentFlag, struct FTW* internalFtwUsage) {
    gTotalBytes+=  statPtr->st_size;
    return 0;  //ntfw continues
 }
} // namespace


size_t RecursiveFolderDiskUsed(const std::string& startPath) {
   const int flags = FTW_DEPTH | FTW_MOUNT | FTW_PHYS;
   const int maxFileDescriptorsToUse = 1024; // or whatever
   const int result = nftw(startPath.c_str(), GetSize, maxFileDescriptorsToUse , flags);

  // log or something if result== -1
  return gTotalBytes;
}

The data is best given static linkage (i.e. file-scope) in a separate module that includes only functions required to access the data, including the function passed to nftw(). That way the data is not visible globally and all access is controlled. It may be that the function that calls ntfw() is also part of this module, enabling the function passed to nftw() to also be static, and thus invisible externally.

In other words, you should do what you are probably doing already, but use separate compilation and static linkage judiciously to make the data only visible via access functions. Data with static linkage is accessible by any function within the same translation unit, and you avoid the problems associated with global variables by only including functions in that translation unit that are creators, maintainers or accessors of that data.

The general pattern is:

datamodule.h

#if defined DATAMODULE_INCLUDE
<type> create_data( <args>) ;
<type> get_data( <args> ) ;
#endif

datamodule.c

#include "datamodule.h"

static <type> my_data ;

static int nftwfunc(const char *filename, const struct stat *statptr, int fileflags, struct FTW *pfwt)
{
    // update/add to my_data
    ...
}


<type> create_data( const char* path, <other args>)
{
    ...

    ret = nftw( path, nftwfunc, fd_limit, flags);

    ... 
}

<type> get_data( <args> )
{
    // Get requested data from my_data and return it to caller
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!