static int foreach_property(const uint32_t off,
        void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
{
    prop_bt *trie = reinterpret_cast<prop_bt*>(to_prop_obj(off));
    if (!trie)
        return -1;

    if (trie->left) {
        const int err = foreach_property(trie->left, propfn, cookie);
        if (err < 0)
            return -1;
    }
    if (trie->prop) {
        prop_info *info = reinterpret_cast<prop_info*>(to_prop_obj(trie->prop));
        if (!info)
            return -1;
        propfn(info, cookie);
    }
    if (trie->children) {
        const int err = foreach_property(trie->children, propfn, cookie);
        if (err < 0)
            return -1;
    }
    if (trie->right) {
        const int err = foreach_property(trie->right, propfn, cookie);
        if (err < 0)
            return -1;
    }

    return 0;
}
bool prop_area::foreach_property(prop_bt *const trie,
        void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
{
    if (!trie)
        return false;

    uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
    if (left_offset != 0) {
        const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
        if (err < 0)
            return false;
    }
    uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
    if (prop_offset != 0) {
        prop_info *info = to_prop_info(&trie->prop);
        if (!info)
            return false;
        propfn(info, cookie);
    }
    uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
    if (children_offset != 0) {
        const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
        if (err < 0)
            return false;
    }
    uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
    if (right_offset != 0) {
        const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
        if (err < 0)
            return false;
    }

    return true;
}
int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
        void *cookie)
{
    if (__predict_false(compat_mode)) {
        return __system_property_foreach_compat(propfn, cookie);
    }

    return foreach_property(0, propfn, cookie);
}
bool prop_area::foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
    return foreach_property(root_node(), propfn, cookie);
}