Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storing and returning pointer values? #54

Open
ArcaneEngineer opened this issue Sep 4, 2015 · 2 comments
Open

Storing and returning pointer values? #54

ArcaneEngineer opened this issue Sep 4, 2015 · 2 comments

Comments

@ArcaneEngineer
Copy link

I'm replacing my own map implementation with khash in a given project. My old map could return pointers or values. This pattern still makes sense for my project. However, khash is built to return values for performance reasons, I believe, so returning pointers reliably isn't really supported, FWICS (?).

I'd like to use khash for both performance-critical and less demanding work where I just need string-key/pointer-value pairs, so am here to ask, what would you do to store/return a pointer in a khash map?

I can see 3 ways:

  • Use khash to store array indices rather than pointers... but here we'd have to also ref into that array
  • Hack it using int64_t... this should theoretically work on systems with smaller word sizes as well, but it seems a bit dodgy... my project needs to work for Arm (32-bit) & Intel (64-bit)
  • The better solution seems to be to use intptr_t as the value type, but am worried this will have some problems.

Any advice greatly appreciated.

@ArcaneEngineer ArcaneEngineer changed the title Pointer values Storing and returning pointer values? Sep 4, 2015
@attractivechaos
Copy link
Owner

You can have something like this (you would like to use a better hash function as pointers are not random):

#if UINTPTR_MAX == UINT64_MAX
static inline uint32_t hash_intptr(uintptr_t key) // by Thomas Wang
{
  key = (~key) + (key << 18);
  key = key ^ (key >> 31);
  key = (key + (key << 2)) + (key << 4);
  key = key ^ (key >> 11);
  key = key + (key << 6);
  key = key ^ (key >> 22);
  return (uint32_t)key;
}
#else
static inline uint32_t hash_intptr(uintptr_t key)
{
  key = ~key + (key << 15);
  key = key ^ (key >> 12);
  key = key + (key << 2);
  key = key ^ (key >> 4);
  key = (key + (key << 3)) + (key << 11);
  key = key ^ (key >> 16);
  return key;
}
#endif

#define my_hash_eq(a,b) ((a)==(b))
KHASH_INIT(name, uintptr_t, value_type, 1, hash_intptr, my_hash_eq)

Probably there are better ways to test the size of uintptr_t.

@ArcaneEngineer
Copy link
Author

Thanks. Actually my original question didn't make sense (I was thinking of applying hash and equals to values... eh!) It was relatively simple in the end.

In my header:
static const int StrPtr = 36;
KHASH_DECLARE(StrPtr, kh_cstr_t, uintptr_t)

In my source (note, I have removed static from khash's SCOPE to get things working; YMMV):

__KHASH_IMPL(StrPtr, kh_inline klib_unused, kh_cstr_t, uintptr_t, 1, kh_str_hash_func, kh_str_hash_equal)

And of course the khash instance is set up as:

khash_t(StrPtr) * devicesByName = kh_init(StrPtr);

And access is as all other examples. For now, this seems to be working. This issue can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants