设计头文件时,应使头文件可以多次包含在同一个源文件中。必须要保证多次包含同一头文件不会引起该头文件定义类和对象被多次定义。
使用预处理器定义头文件保护符。头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容。
避免多重包含,在编写头文件之前,需要引入一些额外的预处理器设施,预处理器允许我们自定义变量。
预处理器变量的名字在程序中必须是唯一的。任何与预处理器变量相匹配的名字的使用都关联到该预处理器变量。
为了避免名字冲突,预处理器变量经常用大写字母表示。
预处理器变量有两种状态:已定义或未定义。定义预处理器变量和检测其状态所用的预处理器指示不同。
#define 指示接受一个名字并定义该名字为预处理变量。
#ifndef 指示检测指定的预处理器变量是否未定义。如果预处理器变量未定义,那么跟在其后的所有指示都被处理。直到出现#endif。
可以用这些设施来预防多次包含同一个头文件。
#ifndef NDEBUG
/* Print field value into debug trace, in NULL-aware way. */
void dbug_print() const {
if (is_real_null())
fprintf(DBUG_FILE, "NULL");
else {
char buf[256];
String str(buf, sizeof(buf), &my_charset_bin);
str.length(0);
String *pstr;
pstr = val_str(&str);
fprintf(DBUG_FILE, "'%s'", pstr->c_ptr_safe());
}
}
#endif
条件指示
#ifndef FIELD_INCLUDED
测试FIELD_INCLUDED 预处理器变量是否未定义。
如果FIELD_INCLUDED未定义,那么#ifndef测试成功,跟在#ifndef后面的所有行都被执行。直到发现#endif.
相反,如果FIELD_INCLUDED 已经定义,那么#ifndef 指示测试为假
,该指示和#endif 指示间的代码都被忽略。
#ifndef UNIV_HOTBACKUP
/** Checks if the page in the cursor can be merged with given page.
If necessary, re-organize the merge_page.
@return true if possible to merge. */
static bool btr_can_merge_with_page(
btr_cur_t *cursor, /*!< in: cursor on the page to merge */
page_no_t page_no, /*!< in: a sibling page */
buf_block_t **merge_block, /*!< out: the merge block */
mtr_t *mtr); /*!< in: mini-transaction */
#endif
/** Checks if the page in the cursor can be merged with given page.
If necessary, re-organize the merge_page.
@return true if possible to merge. */
static bool btr_can_merge_with_page(
btr_cur_t *cursor, /*!< in: cursor on the page to merge */
page_no_t page_no, /*!< in: a sibling page */
buf_block_t **merge_block, /*!< out: the merge block */
mtr_t *mtr) /*!< in: mini-transaction */
{
dict_index_t *index;
page_t *page;
ulint n_recs;
ulint data_size;
ulint max_ins_size_reorg;
ulint max_ins_size;
buf_block_t *mblock;
page_t *mpage;
DBUG_TRACE;
if (page_no == FIL_NULL) {
*merge_block = nullptr;
return false;
}
index = btr_cur_get_index(cursor);
page = btr_cur_get_page(cursor);
const page_id_t page_id(dict_index_get_space(index), page_no);
const page_size_t page_size(dict_table_page_size(index->table));
mblock = btr_block_get(page_id, page_size, RW_X_LATCH, index, mtr);
mpage = buf_block_get_frame(mblock);
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
max_ins_size_reorg = page_get_max_insert_size_after_reorganize(mpage, n_recs);
if (data_size > max_ins_size_reorg) {
goto error;
}
/* If compression padding tells us that merging will result in
too packed up page i.e.: which is likely to cause compression
failure then don't merge the pages. */
if (page_size.is_compressed() && page_is_leaf(mpage) &&
(page_get_data_size(mpage) + data_size >=
dict_index_zip_pad_optimal_page_size(index))) {
goto error;
}
max_ins_size = page_get_max_insert_size(mpage, n_recs);
if (data_size > max_ins_size) {
/* We have to reorganize mpage */
if (!btr_page_reorganize_block(false, page_zip_level, mblock, index, mtr)) {
goto error;
}
max_ins_size = page_get_max_insert_size(mpage, n_recs);
ut_ad(page_validate(mpage, index));
ut_ad(max_ins_size == max_ins_size_reorg);
if (data_size > max_ins_size) {
/* Add fault tolerance, though this should
never happen */
goto error;
}
}
*merge_block = mblock;
return true;
error:
*merge_block = nullptr;
return false;
}