auto_weak.h   [plain text]


/*
 * Copyright (c) 2011 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */
/* 
    auto_weak.h
    Weak reference accounting
    Copyright (c) 2004-2011 Apple Inc. All rights reserved.
 */

#ifndef __AUTO_WEAK__
#define __AUTO_WEAK__

#define AUTO_USE_NEW_WEAK_CALLBACK
#include "auto_impl_utilities.h"

__BEGIN_DECLS

namespace Auto {
    class Zone;
}

/*
The weak table is a hash table governed by a single spin lock.
An allocated blob of memory, most often an object, but under GC any such allocation,
may have its address stored in a __weak marked storage location through use of
compiler generated write-barriers or hand coded uses of the register weak primitive.
Associated with the registration can be a callback block for the case when one of
 the allocated chunks of memory is reclaimed.
The table is hashed on the address of the allocated memory.  When __weak marked memory
 changes its reference, we count on the fact that we can still see its previous reference.

So, in the hash table, indexed by the weakly referenced item, is a list of all locations
 where this address is currently being stored.
 
*/

struct weak_referrer_t {
    void **referrer;    // clear this address
    auto_weak_callback_block_t *block;
};
typedef struct weak_referrer_t weak_referrer_t;

// clear references to garbage
extern auto_weak_callback_block_t *weak_clear_references(Auto::Zone *azone, size_t garbage_count, vm_address_t *garbage, uintptr_t *weak_referents_count, uintptr_t *weak_refs_count);

// register a new weak reference
extern void weak_register(Auto::Zone *azone, const void *referent, void **referrer, auto_weak_callback_block_t *block);

// unregister an existing weak reference
extern void weak_unregister(Auto::Zone *azone, const void *referent, void **referrer);

// unregister all weak references from a block.
extern void weak_unregister_with_layout(Auto::Zone *azone, void *block[], const unsigned char *map);

// unregister weak references in a block range.
extern void weak_unregister_range(Auto::Zone *azone, void **referrers, size_t count);

// call all registered weak reference callbacks.
extern void weak_call_callbacks(auto_weak_callback_block_t *block);

// unregister all weak references within a known address range.
extern void weak_unregister_data_segment(Auto::Zone *azone, void *base, size_t size);

// NOTE:  the remaining routines all assume the weak lock is held by the caller.

// forwards weak references from oldReferent to newReferent.
extern void weak_transfer_weak_referents(Auto::Zone *azone, const void *oldReferent, const void *newReferent);
extern void weak_transfer_weak_contents(Auto::Zone *azone, void *oldBlock[], void *newBlock[], const uint8_t *map);
extern void weak_transfer_weak_contents_unscanned(Auto::Zone *azone, void *oldBlock[], void *newBlock[], size_t size, bool forwarding);

// unregister weak references in a block range.
extern void weak_unregister_range_no_lock(Auto::Zone *azone, void **referrers, size_t count);

#ifdef __BLOCKS__

typedef void (^weak_ref_visitor_t) (const weak_referrer_t &ref);

// dump just the weak references to this block.
extern void weak_enumerate_weak_references(Auto::Zone *azone, const void *referent, weak_ref_visitor_t visitor);

// dump all weak registrations
extern void weak_enumerate_table(Auto::Zone *azone, weak_ref_visitor_t visitor);

// fixup all weak registrations (compaction)
typedef void (^weak_ref_fixer_t) (weak_referrer_t &ref);
extern void weak_enumerate_table_fixup(Auto::Zone *azone, weak_ref_fixer_t fixer);

#endif

__END_DECLS

#endif /* __AUTO_WEAK__ */